| <!doctype html> |
| <meta charset=utf-8> |
| <meta name="timeout" content="long"> |
| <title>RTCPeerConnection-transceivers.https.html</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="RTCPeerConnection-helper.js"></script> |
| <script> |
| 'use strict'; |
| |
| async function waitForTimeout(t, timeout_ms = 5000) { |
| return new Promise(r => t.step_timeout(r, timeout_ms)); |
| } |
| |
| // The following helper functions are called from RTCPeerConnection-helper.js: |
| // exchangeOffer |
| // exchangeOfferAndListenToOntrack |
| // exchangeAnswer |
| // exchangeAnswerAndListenToOntrack |
| // addEventListenerPromise |
| // createPeerConnectionWithCleanup |
| // createTrackAndStreamWithCleanup |
| // findTransceiverForSender |
| |
| promise_test(async t => { |
| const pc1 = createPeerConnectionWithCleanup(t); |
| pc1.addTrack(... await createTrackAndStreamWithCleanup(t)); |
| const pc2 = createPeerConnectionWithCleanup(t); |
| exchangeIceCandidates(pc1, pc2); |
| |
| let muteWatcher; |
| let unmutePromise; |
| // The unmuting it timing sensitive so we hook up to the event directly |
| // instead of wrapping it in an EventWatcher which uses promises. |
| pc2.ontrack = t.step_func(e => { |
| assert_true(e.track.muted, 'track is muted in ontrack'); |
| muteWatcher = new EventWatcher(t, e.track, ['unmute'], |
| () => waitForTimeout(t)); |
| unmutePromise = muteWatcher.wait_for('unmute'); |
| pc2.ontrack = t.step_func(e => { |
| assert_unreached('ontrack fired unexpectedly'); |
| }); |
| }); |
| await exchangeOfferAnswer(pc1, pc2); |
| await unmutePromise; |
| }, 'ontrack: track goes from muted to unmuted'); |
| |
| promise_test(async t => { |
| const pc1 = createPeerConnectionWithCleanup(t); |
| const pc1Sender = pc1.addTrack(... await createTrackAndStreamWithCleanup(t)); |
| const localTransceiver = findTransceiverForSender(pc1, pc1Sender); |
| const pc2 = createPeerConnectionWithCleanup(t); |
| exchangeIceCandidates(pc1, pc2); |
| |
| let muteWatcher; |
| let unmutePromise; |
| pc2.ontrack = t.step_func(e => { |
| muteWatcher = new EventWatcher(t, e.track, ['mute', 'unmute'], |
| () => waitForTimeout(t)); |
| unmutePromise = muteWatcher.wait_for('unmute'); |
| }); |
| await exchangeOfferAnswer(pc1, pc2); |
| // Need to wait for the initial unmute event before renegotiating, otherwise |
| // there will be no transition from unmuted->muted. |
| await unmutePromise; |
| |
| const mutePromise = muteWatcher.wait_for('mute'); |
| localTransceiver.direction = 'inactive'; |
| await exchangeOfferAnswer(pc1, pc2); |
| |
| await mutePromise; |
| }, 'Changing transceiver direction to \'inactive\' mutes the remote track'); |
| |
| promise_test(async t => { |
| const pc1 = createPeerConnectionWithCleanup(t); |
| const pc1Sender = pc1.addTrack(... await createTrackAndStreamWithCleanup(t)); |
| const localTransceiver = findTransceiverForSender(pc1, pc1Sender); |
| const pc2 = createPeerConnectionWithCleanup(t); |
| exchangeIceCandidates(pc1, pc2); |
| |
| let muteWatcher; |
| let unmutePromise; |
| pc2.ontrack = t.step_func(e => { |
| muteWatcher = new EventWatcher(t, e.track, ['mute', 'unmute'], |
| () => waitForTimeout(t)); |
| unmutePromise = muteWatcher.wait_for('unmute'); |
| }); |
| await exchangeOfferAnswer(pc1, pc2); |
| await unmutePromise; |
| |
| const mutePromise = muteWatcher.wait_for('mute'); |
| localTransceiver.direction = 'inactive'; |
| await exchangeOfferAnswer(pc1, pc2); |
| await mutePromise; |
| |
| unmutePromise = muteWatcher.wait_for('unmute'); |
| localTransceiver.direction = 'sendrecv'; |
| await exchangeOfferAnswer(pc1, pc2); |
| |
| await unmutePromise; |
| }, 'Changing transceiver direction to \'sendrecv\' unmutes the remote track'); |
| |
| promise_test(async t => { |
| const pc1 = createPeerConnectionWithCleanup(t); |
| const pc1Sender = pc1.addTrack(... await createTrackAndStreamWithCleanup(t)); |
| const localTransceiver = findTransceiverForSender(pc1, pc1Sender); |
| const pc2 = createPeerConnectionWithCleanup(t); |
| exchangeIceCandidates(pc1, pc2); |
| |
| let muteWatcher; |
| let unmutePromise; |
| pc2.ontrack = t.step_func(e => { |
| muteWatcher = new EventWatcher(t, e.track, ['mute', 'unmute'], |
| () => waitForTimeout(t)); |
| unmutePromise = muteWatcher.wait_for('unmute'); |
| }); |
| await exchangeOfferAnswer(pc1, pc2); |
| // Need to wait for the initial unmute event before closing, otherwise |
| // there will be no transition from unmuted->muted. |
| await unmutePromise; |
| |
| // This will send an RTCP BYE which causes the remote side to mute. |
| const mutePromise = muteWatcher.wait_for('mute'); |
| localTransceiver.stop(); |
| await mutePromise; |
| }, 'transceiver.stop() on one side (without renegotiation) causes mute events on the other'); |
| |
| promise_test(async t => { |
| const pc1 = createPeerConnectionWithCleanup(t); |
| const pc1Sender = pc1.addTrack(...await createTrackAndStreamWithCleanup(t)); |
| const localTransceiver = findTransceiverForSender(pc1, pc1Sender); |
| const pc2 = createPeerConnectionWithCleanup(t); |
| exchangeIceCandidates(pc1, pc2); |
| |
| let muteWatcher; |
| let unmutePromise; |
| pc2.ontrack = t.step_func(e => { |
| muteWatcher = new EventWatcher(t, e.track, ['mute', 'unmute'], |
| () => waitForTimeout(t)); |
| unmutePromise = muteWatcher.wait_for('unmute'); |
| }); |
| await exchangeOfferAnswer(pc1, pc2); |
| // Need to wait for the initial unmute event before closing, otherwise |
| // there will be no transition from unmuted->muted. |
| await unmutePromise; |
| |
| const mutePromise = muteWatcher.wait_for('mute'); |
| pc1.close(); |
| await mutePromise; |
| }, 'pc.close() on one side causes mute events on the other'); |
| </script> |