rtp-extension-support.html (2983B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>RTCPeerConnection RTP extensions</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="../third_party/sdp/sdp.js"></script> 7 <script> 8 'use strict'; 9 10 async function setup() { 11 const pc1 = new RTCPeerConnection(); 12 pc1.addTransceiver('audio'); 13 // Make sure there is more than one rid, since there's no reason to use 14 // rtp-stream-id/repaired-rtp-stream-id otherwise. Some implementations 15 // may use them for unicast anyway, which isn't a spec violation, just 16 // a little silly. 17 pc1.addTransceiver('video', {sendEncodings: [{rid: '0'}, {rid: '1'}]}); 18 const offer = await pc1.createOffer(); 19 pc1.close(); 20 return offer.sdp; 21 } 22 23 // Extensions that MUST be supported 24 const mandatoryExtensions = [ 25 // Directly referenced in WebRTC RTP usage 26 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', // RFC 8834 5.2.2 27 'urn:ietf:params:rtp-hdrext:sdes:mid', // RFC 8834 5.2.4 28 'urn:3gpp:video-orientation', // RFC 8834 5.2.5 29 // Required for support of simulcast with RID 30 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', // RFC 8852 4.3 31 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id', // RFC 8852 4.4 32 ]; 33 34 // For further testing: 35 // - Add test for rapid synchronization - RFC 8834 5.2.1 36 // - Add test for encrypted header extensions (RFC 6904) 37 // - Separate tests for extensions in audio and video sections 38 39 for (const extension of mandatoryExtensions) { 40 promise_test(async t => { 41 const sdp = await setup(); 42 const extensions = SDPUtils.matchPrefix(sdp, 'a=extmap:') 43 .map(SDPUtils.parseExtmap); 44 assert_true(!!extensions.find(ext => ext.uri === extension)); 45 }, `RTP header extension ${extension} is present in offer`); 46 } 47 48 // Test for illegal remote behavior: Reassignment of hdrext ID 49 // in a subsequent offer/answer cycle. 50 promise_test(async t => { 51 const pc1 = new RTCPeerConnection(); 52 t.add_cleanup(() => pc1.close()); 53 const pc2 = new RTCPeerConnection(); 54 t.add_cleanup(() => pc2.close()); 55 56 pc1.addTransceiver('audio'); 57 await pc1.setLocalDescription(); 58 await pc2.setRemoteDescription(pc1.localDescription); 59 await pc2.setLocalDescription(); 60 await pc1.setRemoteDescription(pc2.localDescription); 61 // Do a second offer/answer cycle. 62 await pc1.setLocalDescription(); 63 await pc2.setRemoteDescription(pc1.localDescription); 64 const answer = await pc2.createAnswer(); 65 66 // Swap the extension number of the two required extensions 67 answer.sdp = answer.sdp.replace('urn:ietf:params:rtp-hdrext:ssrc-audio-level', 68 'xyzzy') 69 .replace('urn:ietf:params:rtp-hdrext:sdes:mid', 70 'urn:ietf:params:rtp-hdrext:ssrc-audio-level') 71 .replace('xyzzy', 72 'urn:ietf:params:rtp-hdrext:sdes:mid'); 73 74 return promise_rejects_dom(t, 'InvalidAccessError', 75 pc1.setRemoteDescription(answer)); 76 }, 'RTP header extension reassignment causes failure'); 77 78 </script>