RTCRtpEncodingParameters-codec-opus-stereo.https.html (4459B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>RTCRtpEncodingParameters codec opus stereo</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script> 7 'use strict'; 8 9 const kNumChannelsMono = 1; 10 const kNumChannelsStereo = 2; 11 const kAudioProcessingEnabled = true; 12 const kAudioProcessingDisabled = false; 13 14 // In some implementations (e.g. Chrome), whether or not audio processing is 15 // used may affect the number of channels we get. 16 // To isolate this factor from the test, we constrain both channels and APM. 17 function getAudioConstraints(numChannels, audioProcessing) { 18 return { 19 channelCount: {exact: numChannels}, 20 autoGainControl: audioProcessing, 21 echoCancellation: audioProcessing, 22 noiseSuppression: audioProcessing 23 }; 24 } 25 26 // Polls getSettings() until `channelCount` is known. 27 // Remote tracks don't populate their `channelCount` until media is received. 28 async function pollChannelCount(t, track) { 29 while (true) { 30 if (track.getSettings().channelCount != undefined) { 31 break; 32 } 33 await new Promise(r => t.step_timeout(r, 50)); 34 } 35 return track.getSettings().channelCount; 36 } 37 38 promise_test(async t => { 39 const pc1 = new RTCPeerConnection(); 40 t.add_cleanup(() => pc1.close()); 41 const pc2 = new RTCPeerConnection(); 42 t.add_cleanup(() => pc2.close()); 43 pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate); 44 pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate); 45 46 // Open microphone as mono. 47 const stream = await navigator.mediaDevices.getUserMedia( 48 {audio: getAudioConstraints(kNumChannelsMono, kAudioProcessingEnabled)}); 49 const [track] = stream.getTracks(); 50 t.add_cleanup(() => track.stop()); 51 // Prerequisite of the test. 52 assert_equals(track.getSettings().channelCount, 1, 53 'Can open track in mono'); 54 55 // Negotiate opus. 56 const transceiver = pc1.addTransceiver(track); 57 transceiver.setCodecPreferences( 58 RTCRtpSender.getCapabilities('audio').codecs.filter( 59 codec => codec.mimeType == 'audio/opus')); 60 await pc1.setLocalDescription(); 61 await pc2.setRemoteDescription(pc1.localDescription); 62 await pc2.setLocalDescription(); 63 await pc1.setRemoteDescription(pc2.localDescription); 64 65 const [receiver] = pc2.getReceivers(); 66 const remoteTrack = receiver.track; 67 // Attaching the track to an audio element is needed for media to flow, 68 // otherwise the `channelCount` is never known. 69 const audio = document.createElement('audio'); 70 audio.srcObject = new MediaStream(); 71 audio.srcObject.addTrack(remoteTrack); 72 // The stereo opus decoder outputs stereo regardless of the signal on the 73 // wire. 74 assert_equals(await pollChannelCount(t, remoteTrack), 2, 75 'Remote track is stereo (despite local track being mono)'); 76 }, 'Sending and receiving a mono track with opus (stereo decoder upmix)'); 77 78 promise_test(async t => { 79 const pc1 = new RTCPeerConnection(); 80 t.add_cleanup(() => pc1.close()); 81 const pc2 = new RTCPeerConnection(); 82 t.add_cleanup(() => pc2.close()); 83 pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate); 84 pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate); 85 86 // Open microphone as stereo. 87 const stream = await navigator.mediaDevices.getUserMedia( 88 {audio: getAudioConstraints(kNumChannelsStereo, kAudioProcessingDisabled)}); 89 const [track] = stream.getTracks(); 90 t.add_cleanup(() => track.stop()); 91 // Prerequisite of the test. 92 assert_equals(track.getSettings().channelCount, 2, 93 'Can open track in stereo'); 94 95 // Negotiate opus. 96 const transceiver = pc1.addTransceiver(track); 97 transceiver.setCodecPreferences( 98 RTCRtpSender.getCapabilities('audio').codecs.filter( 99 codec => codec.mimeType == 'audio/opus')); 100 await pc1.setLocalDescription(); 101 await pc2.setRemoteDescription(pc1.localDescription); 102 await pc2.setLocalDescription(); 103 await pc1.setRemoteDescription(pc2.localDescription); 104 105 const [receiver] = pc2.getReceivers(); 106 const remoteTrack = receiver.track; 107 // Attaching the track to an audio element is needed for media to flow, 108 // otherwise the `channelCount` is never known. 109 const audio = document.createElement('audio'); 110 audio.srcObject = new MediaStream(); 111 audio.srcObject.addTrack(remoteTrack); 112 assert_equals(await pollChannelCount(t, remoteTrack), 2, 113 'Remote track is also stereo'); 114 }, 'Sending and receiving a stereo track with opus'); 115 </script>