| <!doctype html> | |
| <meta charset=utf-8> | |
| <title>RTCPeerConnection: media flows to a second unidirectional transceiver added through renegotiation.</title> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="RTCPeerConnection-helper.js"></script> | |
| <script> | |
| 'use strict'; | |
| async function doTest(t, kind, firstTransceiverDirection) { | |
| const pc1 = new RTCPeerConnection(); | |
| const pc2 = new RTCPeerConnection(); | |
| t.add_cleanup(() => pc1.close()); | |
| t.add_cleanup(() => pc2.close()); | |
| exchangeIceCandidates(pc1, pc2); | |
| // Add a transceiver that we won't use and negotiate. | |
| pc1.addTransceiver(kind, {direction: "recvonly"}); | |
| await pc1.setLocalDescription(); | |
| await pc2.setRemoteDescription(pc1.localDescription); | |
| const [sendTransceiver1] = pc2.getTransceivers(); | |
| sendTransceiver1.direction = firstTransceiverDirection; | |
| await pc2.setLocalDescription(); | |
| await pc1.setRemoteDescription(pc2.localDescription); | |
| // Add another transceiver, that we will use, and renegotiate. | |
| const stream = await getNoiseStream({[kind]: true}); | |
| const [track] = stream.getTracks(); | |
| t.add_cleanup(() => track.stop()); | |
| pc1.addTransceiver(kind, {direction: "recvonly"}); | |
| await pc1.setLocalDescription(); | |
| await pc2.setRemoteDescription(pc1.localDescription); | |
| const [, sendTransceiver2] = pc2.getTransceivers(); | |
| sendTransceiver2.direction = "sendonly"; | |
| sendTransceiver2.sender.replaceTrack(track); | |
| await pc2.setLocalDescription(); | |
| await pc1.setRemoteDescription(pc2.localDescription); | |
| const [, recvTransceiver] = pc1.getTransceivers(); | |
| const {receiver} = recvTransceiver; | |
| const threshold = 10; | |
| let inboundStats, timedout = false; | |
| t.step_timeout(() => timedout = true, 2000); | |
| while (!timedout) { | |
| const stats = await receiver.getStats(); | |
| inboundStats = [...stats.values()].find(({type}) => type == "inbound-rtp"); | |
| if (inboundStats?.packetsReceived > threshold) break; | |
| await new Promise(r => t.step_timeout(r, 50)); | |
| } | |
| assert_greater_than(inboundStats?.packetsReceived, | |
| threshold, | |
| "packets received indicates media flow." | |
| ); | |
| } | |
| promise_test(async t => { | |
| await doTest(t, "video", "sendonly"); | |
| }, "Video flows to RTCPeerConnection's second transceiver added through renegotiation, with first transceiver also sending"); | |
| promise_test(async t => { | |
| await doTest(t, "audio", "sendonly"); | |
| }, "Audio flows to RTCPeerConnection's second transceiver added through renegotiation, with first transceiver also sending"); | |
| promise_test(async t => { | |
| await doTest(t, "video", "inactive"); | |
| }, "Video flows to RTCPeerConnection's second transceiver added through renegotiation, with first transceiver inactive"); | |
| promise_test(async t => { | |
| await doTest(t, "audio", "inactive"); | |
| }, "Audio flows to RTCPeerConnection's second transceiver added through renegotiation, with first transceiver inactive"); | |
| </script> |