RTCRtpReceiver-video-anyCodec.html (3914B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Tests that RTCRtpReceiver is prepared to receive any negotiated video codec</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/webrtc/RTCPeerConnection-helper.js"></script> 7 <script src="/webrtc/third_party/sdp/sdp.js"></script> 8 <body> 9 <script> 10 'use strict' 11 12 function filterOnlySecondaryCodec(description) { 13 const sections = SDPUtils.splitSections(description.sdp); 14 const dtls = SDPUtils.getDtlsParameters(sections[1], sections[0]); 15 const ice = SDPUtils.getIceParameters(sections[1], sections[0]); 16 const rtpParameters = SDPUtils.parseRtpParameters(sections[1]); 17 const setupValue = SDPUtils.matchPrefix(description.sdp, 'a=setup:')[0].substring(8); 18 const mline = SDPUtils.parseMLine(sections[1]); 19 20 // Of all the codecs in the description, filter out one that has multiple 21 // payload types, and use only one of those payload types that is not the 22 // preferred codec. 23 // 24 // Ideally this would test all PTs through RTCRtpSender.setParameters, but 25 // Firefox does not at this time support RTCRtpEncodingParameters.codec: 26 // https://bugzilla.mozilla.org/show_bug.cgi?id=1894137 27 const codecs = {}; 28 for (const codec of rtpParameters.codecs) { 29 if (["RED", "RTX", "ULPFEC"].includes(codec.name.toUpperCase())) { 30 continue; 31 } 32 codecs[codec.name] ??= []; 33 codecs[codec.name].push(codec); 34 } 35 36 const multipleCodecs = []; 37 for (const name of Object.keys(codecs)) { 38 if (codecs[name].length > 1) { 39 multipleCodecs.push(codecs[name]); 40 } 41 } 42 43 assert_implements_optional(multipleCodecs.length > 0, 'No codec with multiple payload types'); 44 45 const multiplePtsCodecs = multipleCodecs[0]; 46 const nonPreferredCodec = multiplePtsCodecs[1]; 47 rtpParameters.codecs = [nonPreferredCodec]; 48 49 return SDPUtils.writeSessionBoilerplate() + 50 SDPUtils.writeDtlsParameters(dtls, setupValue) + 51 SDPUtils.writeIceParameters(ice) + 52 SDPUtils.writeRtpDescription(mline.kind, rtpParameters); 53 } 54 55 promise_test(async t => { 56 const pc1 = new RTCPeerConnection(); 57 t.add_cleanup(() => pc1.close()); 58 const pc2 = new RTCPeerConnection(); 59 t.add_cleanup(() => pc2.close()); 60 pc1.onicecandidate = ({candidate}) => pc2.addIceCandidate(candidate); 61 pc2.onicecandidate = ({candidate}) => pc1.addIceCandidate(candidate); 62 63 const [track] = (await getNoiseStream({video: true})).getTracks(); 64 t.add_cleanup(() => track.stop()); 65 pc1.addTrack(track); 66 67 await pc1.setLocalDescription(); 68 await pc2.setRemoteDescription(pc1.localDescription); 69 await pc2.setLocalDescription(); 70 71 const nonPreferredAnswer = {type: 'answer', sdp: filterOnlySecondaryCodec(pc2.localDescription)}; 72 await pc1.setRemoteDescription(nonPreferredAnswer); 73 74 // Verify that the right payloadType is sent, *and* received. 75 const start = performance.now(); 76 const timeoutThreshold = start + 5000; 77 while (true) { 78 const stats = [...(await pc1.getStats()).values()].find(({type}) => type === 'outbound-rtp'); 79 if (stats?.framesSent > 0) { 80 break; 81 } 82 if (performance.now() > timeoutThreshold) { 83 assert_unreached("Timed out waiting for sent frames"); 84 } 85 await new Promise(r => t.step_timeout(r, 100)); 86 } 87 88 while (true) { 89 const stats = [...(await pc2.getStats()).values()].find(({type}) => type === 'inbound-rtp'); 90 if (stats?.framesReceived > 0) { 91 break; 92 } 93 if (performance.now() > timeoutThreshold) { 94 assert_unreached("Timed out waiting for received frames"); 95 } 96 await new Promise(r => t.step_timeout(r, 100)); 97 } 98 }, 'An RTCRtpReceiver is prepared to receive any negotiated codec.'); 99 100 </script> 101 </body>