h265-loopback.https.html (2722B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <meta name="timeout" content="long"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="../RTCPeerConnection-helper.js"></script> 7 <script> 8 'use strict'; 9 10 async function pollGetStatsUntil(t, pc, condition, pollingMs = 100) { 11 while (true) { 12 const report = await pc.getStats(); 13 for (const stats of report.values()) { 14 if (condition(report, stats) == true) { 15 // Condition satisfied, stop polling. 16 return; 17 } 18 } 19 await new Promise(r => t.step_timeout(r, pollingMs)); 20 } 21 } 22 23 function isRtpWithCodec(report, stats, mimeType) { 24 if (stats.type != 'outbound-rtp' && stats.type != 'inbound-rtp') { 25 return false; // Not an RTP stats object. 26 } 27 const codec = report.get(stats.codecId); 28 return codec && codec.mimeType == mimeType; 29 } 30 31 promise_test(async t => { 32 const sendCodec = RTCRtpSender.getCapabilities('video').codecs.find( 33 codec => codec.mimeType == 'video/H265'); 34 const recvCodec = RTCRtpReceiver.getCapabilities('video').codecs.find( 35 codec => codec.mimeType == 'video/H265'); 36 assert_implements_optional( 37 sendCodec != undefined && recvCodec != undefined, 38 'H265 not available for sending or receiving. Loopback requires both.'); 39 40 const pc1 = new RTCPeerConnection(); 41 t.add_cleanup(() => pc1.close()); 42 const pc2 = new RTCPeerConnection(); 43 t.add_cleanup(() => pc2.close()); 44 pc1.onicecandidate = (e) => pc2.addIceCandidate(e.candidate); 45 pc2.onicecandidate = (e) => pc1.addIceCandidate(e.candidate); 46 47 const stream = await getNoiseStream({video:{width:640, height:360}}); 48 const [track] = stream.getVideoTracks(); 49 t.add_cleanup(() => track.stop()); 50 51 // Negotiate H265. 52 const transceiver = pc1.addTransceiver(track); 53 transceiver.setCodecPreferences([sendCodec]); 54 await pc1.setLocalDescription(); 55 await pc2.setRemoteDescription(pc1.localDescription); 56 await pc2.setLocalDescription(); 57 await pc1.setRemoteDescription(pc2.localDescription); 58 59 // Wait for H265 frames to be encoded and sent. 60 await pollGetStatsUntil(t, pc1, (report, stats) => { 61 if (!isRtpWithCodec(report, stats, 'video/H265')) { 62 return false; 63 } 64 assert_equals(stats.type, 'outbound-rtp'); 65 return stats.framesEncoded > 0 && stats.framesSent > 0; 66 }); 67 // Wait for H265 frames to be received and decoded. 68 await pollGetStatsUntil(t, pc2, (report, stats) => { 69 if (!isRtpWithCodec(report, stats, 'video/H265')) { 70 return false; 71 } 72 assert_equals(stats.type, 'inbound-rtp'); 73 return stats.framesReceived > 0 && stats.framesDecoded > 0; 74 }); 75 }, `Negotiate H265 loopback and verify frames are flowing`); 76 </script>