--- a/dom/media/tests/mochitest/head.js
+++ b/dom/media/tests/mochitest/head.js
@@ -314,16 +314,17 @@ function setupEnvironment() {
var defaultMochitestPrefs = {
'set': [
['media.peerconnection.enabled', true],
['media.peerconnection.identity.enabled', true],
['media.peerconnection.identity.timeout', 120000],
['media.peerconnection.ice.stun_client_maximum_transmits', 14],
['media.peerconnection.ice.trickle_grace_period', 30000],
+ ['media.peerconnection.remoteTrackId.enabled', true],
['media.navigator.permission.disabled', true],
['media.navigator.streams.fake', FAKE_ENABLED],
['media.getusermedia.screensharing.enabled', true],
['media.getusermedia.audiocapture.enabled', true],
['media.recorder.audio_node.enabled', true]
]
};
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -94,16 +94,17 @@ skip-if = toolkit == 'android' # no scre
[test_getUserMedia_trackEnded.html]
[test_getUserMedia_peerIdentity.html]
[test_peerConnection_addIceCandidate.html]
[test_peerConnection_addtrack_removetrack_events.html]
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_audioCodecs.html]
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_transceivers.html]
+skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_basicAudio.html]
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_checkPacketDumpHook.html]
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_basicAudioNATSrflx.html]
skip-if = toolkit == 'android' || (os == 'linux' && (debug || asan)) # websockets don't work on android (bug 1266217), linux hang (bug 1339568)
[test_peerConnection_basicAudioNATRelay.html]
skip-if = toolkit == 'android' || (os == 'linux' && (debug || asan)) # websockets don't work on android (bug 1266217), linux hang (bug 1339568)
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -145,17 +145,17 @@ PeerConnectionTest.prototype.closePC = f
Promise.all(pc._pc.getReceivers()
.filter(receiver => receiver.track.readyState == "live")
.map(receiver => {
info("Waiting for track " + receiver.track.id + " (" +
receiver.track.kind + ") to end.");
return haveEvent(receiver.track, "ended", wait(50000))
.then(event => {
is(event.target, receiver.track, "Event target should be the correct track");
- info("ended fired for track " + receiver.track.id);
+ info(pc + " ended fired for track " + receiver.track.id);
}, e => e ? Promise.reject(e)
: ok(false, "ended never fired for track " +
receiver.track.id));
}))
]);
pc.close();
return promise;
};
@@ -756,18 +756,20 @@ function PeerConnectionWrapper(label, co
this._local_ice_candidates = [];
this._remote_ice_candidates = [];
this.localRequiresTrickleIce = false;
this.remoteRequiresTrickleIce = false;
this.localMediaElements = [];
this.remoteMediaElements = [];
this.audioElementsOnly = false;
+ this._sendStreams = [];
+
this.expectedLocalTrackInfoById = {};
- this.expectedRemoteTrackInfoById = {};
+ this.expectedSignalledTrackInfoById = {};
this.observedRemoteTrackInfoById = {};
this.disableRtpCountChecking = false;
this.iceConnectedResolve;
this.iceConnectedReject;
this.iceConnected = new Promise((resolve, reject) => {
this.iceConnectedResolve = resolve;
@@ -870,36 +872,70 @@ PeerConnectionWrapper.prototype = {
get iceConnectionState() {
return this._pc.iceConnectionState;
},
setIdentityProvider: function(provider, protocol, identity) {
this._pc.setIdentityProvider(provider, protocol, identity);
},
+ elementPrefix : direction =>
+ {
+ return [this.label, direction].join('_');
+ },
+
+ getMediaElementForTrack : function (track, direction)
+ {
+ var prefix = this.elementPrefix(direction);
+ return getMediaElementForTrack(track, prefix);
+ },
+
+ createMediaElementForTrack : function(track, direction)
+ {
+ var prefix = this.elementPrefix(direction);
+ return createMediaElementForTrack(track, prefix);
+ },
+
ensureMediaElement : function(track, direction) {
- const idPrefix = [this.label, direction].join('_');
- var element = getMediaElementForTrack(track, idPrefix);
-
+ var prefix = this.elementPrefix(direction);
+ var element = this.getMediaElementForTrack(track, direction);
if (!element) {
- element = createMediaElementForTrack(track, idPrefix);
+ element = this.createMediaElementForTrack(track, direction);
if (direction == "local") {
this.localMediaElements.push(element);
} else if (direction == "remote") {
this.remoteMediaElements.push(element);
}
}
// We do this regardless, because sometimes we end up with a new stream with
// an old id (ie; the rollback tests cause the same stream to be added
// twice)
element.srcObject = new MediaStream([track]);
element.play();
},
+ addSendStream : function(stream)
+ {
+ // The PeerConnection will not necessarily know about this stream
+ // automatically, because replaceTrack is not told about any streams the
+ // new track might be associated with. Only content really knows.
+ this._sendStreams.push(stream);
+ },
+
+ getStreamForSendTrack : function(track)
+ {
+ return this._sendStreams.find(str => str.getTrackById(track.id));
+ },
+
+ getStreamForRecvTrack : function(track)
+ {
+ return this._pc.getRemoteStreams().find(s => !!s.getTrackById(track.id));
+ },
+
/**
* Attaches a local track to this RTCPeerConnection using
* RTCPeerConnection.addTrack().
*
* Also creates a media element playing a MediaStream containing all
* tracks that have been added to `stream` using `attachLocalTrack()`.
*
* @param {MediaStreamTrack} track
@@ -916,110 +952,147 @@ PeerConnectionWrapper.prototype = {
ok(track.id, "track has id");
ok(track.kind, "track has kind");
ok(stream.id, "stream has id");
this.expectedLocalTrackInfoById[track.id] = {
type: track.kind,
streamId: stream.id,
};
+ this.expectedSignalledTrackInfoById[track.id] =
+ this.expectedLocalTrackInfoById[track.id];
+
+ this.addSendStream(stream);
// This will create one media element per track, which might not be how
// we set up things with the RTCPeerConnection. It's the only way
// we can ensure all sent tracks are flowing however.
this.ensureMediaElement(track, "local");
return this.observedNegotiationNeeded;
},
/**
* Callback when we get local media. Also an appropriate HTML media element
* will be created and added to the content node.
*
* @param {MediaStream} stream
* Media stream to handle
*/
- attachLocalStream : function(stream) {
+ attachLocalStream : function(stream, useAddTransceiver) {
info("Got local media stream: (" + stream.id + ")");
this.expectNegotiationNeeded();
+ if (useAddTransceiver) {
+ info("Using addTransceiver (on PC).");
+ stream.getTracks().forEach(track => {
+ var transceiver = this._pc.addTransceiver(track, {streams: [stream]});
+ is(transceiver.sender.track, track, "addTransceiver returns sender");
+ });
+ }
// In order to test both the addStream and addTrack APIs, we do half one
// way, half the other, at random.
- if (Math.random() < 0.5) {
+ else if (Math.random() < 0.5) {
info("Using addStream.");
this._pc.addStream(stream);
ok(this._pc.getSenders().find(sender => sender.track == stream.getTracks()[0]),
"addStream returns sender");
} else {
info("Using addTrack (on PC).");
stream.getTracks().forEach(track => {
var sender = this._pc.addTrack(track, stream);
is(sender.track, track, "addTrack returns sender");
});
}
+ this.addSendStream(stream);
+
stream.getTracks().forEach(track => {
ok(track.id, "track has id");
ok(track.kind, "track has kind");
this.expectedLocalTrackInfoById[track.id] = {
type: track.kind,
streamId: stream.id
};
+ this.expectedSignalledTrackInfoById[track.id] =
+ this.expectedLocalTrackInfoById[track.id];
this.ensureMediaElement(track, "local");
});
+
+ return this.observedNegotiationNeeded;
},
removeSender : function(index) {
var sender = this._pc.getSenders()[index];
delete this.expectedLocalTrackInfoById[sender.track.id];
this.expectNegotiationNeeded();
this._pc.removeTrack(sender);
return this.observedNegotiationNeeded;
},
- senderReplaceTrack : function(index, withTrack, withStreamId) {
- var sender = this._pc.getSenders()[index];
+ senderReplaceTrack : function(sender, withTrack, stream) {
delete this.expectedLocalTrackInfoById[sender.track.id];
this.expectedLocalTrackInfoById[withTrack.id] = {
type: withTrack.kind,
- streamId: withStreamId
+ streamId: stream.id
};
+ this.addSendStream(stream);
+ this.ensureMediaElement(withTrack, 'local');
return sender.replaceTrack(withTrack);
},
+ getUserMedia : async function(constraints) {
+ var stream = await getUserMedia(constraints);
+ if (constraints.audio) {
+ stream.getAudioTracks().forEach(track => {
+ info(this + " gUM local stream " + stream.id +
+ " with audio track " + track.id);
+ });
+ }
+ if (constraints.video) {
+ stream.getVideoTracks().forEach(track => {
+ info(this + " gUM local stream " + stream.id +
+ " with video track " + track.id);
+ });
+ }
+ return stream;
+ },
+
/**
* Requests all the media streams as specified in the constrains property.
*
* @param {array} constraintsList
* Array of constraints for GUM calls
*/
getAllUserMedia : function(constraintsList) {
if (constraintsList.length === 0) {
info("Skipping GUM: no UserMedia requested");
return Promise.resolve();
}
info("Get " + constraintsList.length + " local streams");
- return Promise.all(constraintsList.map(constraints => {
- return getUserMedia(constraints).then(stream => {
- if (constraints.audio) {
- stream.getAudioTracks().forEach(track => {
- info(this + " gUM local stream " + stream.id +
- " with audio track " + track.id);
- });
- }
- if (constraints.video) {
- stream.getVideoTracks().forEach(track => {
- info(this + " gUM local stream " + stream.id +
- " with video track " + track.id);
- });
- }
- return this.attachLocalStream(stream);
- });
- }));
+ return Promise.all(
+ constraintsList.map(constraints => this.getUserMedia(constraints))
+ );
+ },
+
+ getAllUserMediaAndAddStreams : async function(constraintsList) {
+ var streams = await this.getAllUserMedia(constraintsList);
+ if (!streams) {
+ return;
+ }
+ return Promise.all(streams.map(stream => this.attachLocalStream(stream)));
+ },
+
+ getAllUserMediaAndAddTransceivers : async function(constraintsList) {
+ var streams = await this.getAllUserMedia(constraintsList);
+ if (!streams) {
+ return;
+ }
+ return Promise.all(streams.map(stream => this.attachLocalStream(stream, true)));
},
/**
* Create a new data channel instance. Also creates a promise called
* `this.nextDataChannel` that resolves when the next data channel arrives.
*/
expectDataChannel: function(message) {
this.nextDataChannel = new Promise(resolve => {
@@ -1159,44 +1232,65 @@ PeerConnectionWrapper.prototype = {
});
},
/**
* Checks whether a given track is expected, has not been observed yet, and
* is of the correct type. Then, moves the track from
* |expectedTrackInfoById| to |observedTrackInfoById|.
*/
- checkTrackIsExpected : function(track,
+ checkTrackIsExpected : function(trackId,
+ kind,
expectedTrackInfoById,
observedTrackInfoById) {
- ok(expectedTrackInfoById[track.id], "track id " + track.id + " was expected");
- ok(!observedTrackInfoById[track.id], "track id " + track.id + " was not yet observed");
- var observedKind = track.kind;
- var expectedKind = expectedTrackInfoById[track.id].type;
+ ok(expectedTrackInfoById[trackId], "track id " + trackId + " was expected");
+ ok(!observedTrackInfoById[trackId], "track id " + trackId + " was not yet observed");
+ var observedKind = kind;
+ var expectedKind = expectedTrackInfoById[trackId].type;
is(observedKind, expectedKind,
- "track id " + track.id + " was of kind " +
+ "track id " + trackId + " was of kind " +
observedKind + ", which matches " + expectedKind);
- observedTrackInfoById[track.id] = expectedTrackInfoById[track.id];
+ observedTrackInfoById[trackId] = expectedTrackInfoById[trackId];
},
isTrackOnPC: function(track) {
- return this._pc.getRemoteStreams().some(s => !!s.getTrackById(track.id));
+ return !!this.getStreamForRecvTrack(track);
},
allExpectedTracksAreObserved: function(expected, observed) {
return Object.keys(expected).every(trackId => observed[trackId]);
},
+ getWebrtcTrackId: function(receiveTrack) {
+ let matchingTransceiver = this._pc.getTransceivers().find(
+ transceiver => transceiver.receiver.track == receiveTrack);
+ if (!matchingTransceiver) {
+ return null;
+ }
+
+ return matchingTransceiver.getRemoteTrackId();
+ },
+
setupTrackEventHandler: function() {
this._pc.addEventListener('track', event => {
- info(this + ": 'ontrack' event fired for " + JSON.stringify(event.track));
+ info(this + ": 'ontrack' event fired for " + event.track.id +
+ "(SDP msid is " + this.getWebrtcTrackId(event.track) +
+ ")");
- this.checkTrackIsExpected(event.track,
- this.expectedRemoteTrackInfoById,
- this.observedRemoteTrackInfoById);
+ // TODO(bug 1403238): Checking for remote tracks needs to be completely
+ // reworked, because with the latest spec the identifiers aren't the same
+ // as they are on the other end. Ultimately, what we need to check is
+ // whether the _transceivers_ are in line with what is expected, and
+ // whether the callbacks are consistent with the transceivers.
+ let trackId = this.getWebrtcTrackId(event.track);
+ ok(!this.observedRemoteTrackInfoById[trackId],
+ "track id " + trackId + " was not yet observed");
+ this.observedRemoteTrackInfoById[trackId] = {
+ type: event.track.kind
+ };
ok(this.isTrackOnPC(event.track), "Found track " + event.track.id);
this.ensureMediaElement(event.track, 'remote');
});
},
/**
* Either adds a given ICE candidate right away or stores it to be added
@@ -1319,53 +1413,47 @@ PeerConnectionWrapper.prototype = {
candidateHandler(this.label, anEvent.candidate);
};
},
checkLocalMediaTracks : function() {
var observed = {};
info(this + " Checking local tracks " + JSON.stringify(this.expectedLocalTrackInfoById));
this._pc.getSenders().forEach(sender => {
- this.checkTrackIsExpected(sender.track, this.expectedLocalTrackInfoById, observed);
+ if (sender.track) {
+ this.checkTrackIsExpected(sender.track.id,
+ sender.track.kind,
+ this.expectedLocalTrackInfoById,
+ observed);
+ }
});
Object.keys(this.expectedLocalTrackInfoById).forEach(
id => ok(observed[id], this + " local id " + id + " was observed"));
},
/**
* Checks that we are getting the media tracks we expect.
*/
checkMediaTracks : function() {
this.checkLocalMediaTracks();
-
- info(this + " Checking remote tracks " +
- JSON.stringify(this.expectedRemoteTrackInfoById));
-
- ok(this.allExpectedTracksAreObserved(this.expectedRemoteTrackInfoById,
- this.observedRemoteTrackInfoById),
- "All expected tracks have been observed"
- + "\nexpected: " + JSON.stringify(this.expectedRemoteTrackInfoById)
- + "\nobserved: " + JSON.stringify(this.observedRemoteTrackInfoById));
},
checkMsids: function() {
var checkSdpForMsids = (desc, expectedTrackInfo, side) => {
Object.keys(expectedTrackInfo).forEach(trackId => {
var streamId = expectedTrackInfo[trackId].streamId;
ok(desc.sdp.match(new RegExp("a=msid:" + streamId + " " + trackId)),
this + ": " + side + " SDP contains stream " + streamId +
" and track " + trackId );
});
};
- checkSdpForMsids(this.localDescription, this.expectedLocalTrackInfoById,
+ checkSdpForMsids(this.localDescription, this.expectedSignalledTrackInfoById,
"local");
- checkSdpForMsids(this.remoteDescription, this.expectedRemoteTrackInfoById,
- "remote");
},
markRemoteTracksAsNegotiated: function() {
Object.values(this.observedRemoteTrackInfoById).forEach(
trackInfo => trackInfo.negotiated = true);
},
rollbackRemoteTracksIfNotNegotiated: function() {
@@ -1456,32 +1544,66 @@ PeerConnectionWrapper.prototype = {
return stats;
}
await wait(retryInterval);
}
throw new Error("Timeout checking for stats for track " + track.id
+ " after at least" + timeout + "ms");
},
+ getExpectedActiveReceiveTracks : function() {
+ return this._pc.getTransceivers()
+ .filter(t => {
+ return !t.stopped &&
+ t.currentDirection &&
+ (t.currentDirection != "inactive") &&
+ (t.currentDirection != "sendonly");
+ })
+ .map(t => {
+ info("Found transceiver that should be receiving RTP: mid=" + t.mid +
+ " currentDirection=" + t.currentDirection + " kind=" +
+ t.receiver.track.kind + " track-id=" + t.receiver.track.id);
+ return t.receiver.track;
+ });
+ },
+
+ getExpectedSendTracks : function() {
+ return Object.keys(this.expectedLocalTrackInfoById)
+ .map(id => this.findSendTrackByWebrtcId(id));
+ },
+
+ findReceiveTrackByWebrtcId : function(webrtcId) {
+ return this._pc.getReceivers().map(receiver => receiver.track)
+ .find(track => this.getWebrtcTrackId(track) == webrtcId);
+ },
+
+ // Send tracks use the same identifiers that go in the signaling
+ findSendTrackByWebrtcId : function(webrtcId) {
+ return this._pc.getSenders().map(sender => sender.track)
+ .filter(track => track) // strip out null
+ .find(track => track.id == webrtcId);
+ },
+
/**
* Wait for presence of video flow on all media elements and rtp flow on
* all sending and receiving track involved in this test.
*
* @returns {Promise}
* A promise that resolves when media flows for all elements and tracks
*/
waitForMediaFlow : function() {
return Promise.all([].concat(
this.localMediaElements.map(element => this.waitForMediaElementFlow(element)),
- Object.keys(this.expectedRemoteTrackInfoById)
- .map(id => this.remoteMediaElements
- .find(e => e.srcObject.getTracks().some(t => t.id == id)))
- .map(e => this.waitForMediaElementFlow(e)),
- this._pc.getSenders().map(sender => this.waitForRtpFlow(sender.track)),
- this._pc.getReceivers().map(receiver => this.waitForRtpFlow(receiver.track))));
+ this.remoteMediaElements.filter(elem =>
+ this.getExpectedActiveReceiveTracks()
+ .some(track => elem.srcObject.getTracks().some(t => t == track))
+ )
+ .map(elem => this.waitForMediaElementFlow(elem)),
+ this.getExpectedActiveReceiveTracks().map(track => this.waitForRtpFlow(track)),
+ this.getExpectedSendTracks().map(track => this.waitForRtpFlow(track))));
},
async waitForSyncedRtcp() {
// Ensures that RTCP is present
let ensureSyncedRtcp = async () => {
let report = await this._pc.getStats();
for (let [k, v] of report) {
if (v.type.endsWith("bound-rtp") && !v.remoteId) {
@@ -1517,69 +1639,100 @@ PeerConnectionWrapper.prototype = {
await wait(waitPeriod);
}
throw Error("Waiting for synced RTCP timed out after at least "
+ maxTime + "ms");
},
/**
* Check that correct audio (typically a flat tone) is flowing to this
- * PeerConnection. Uses WebAudio AnalyserNodes to compare input and output
- * audio data in the frequency domain.
+ * PeerConnection for each transceiver that should be receiving. Uses
+ * WebAudio AnalyserNodes to compare input and output audio data in the
+ * frequency domain.
*
* @param {object} from
* A PeerConnectionWrapper whose audio RTPSender we use as source for
* the audio flow check.
* @returns {Promise}
- * A promise that resolves when we're receiving the tone from |from|.
+ * A promise that resolves when we're receiving the tone/s from |from|.
*/
checkReceivingToneFrom : async function(audiocontext, from,
cancel = wait(60000, new Error("Tone not detected"))) {
- let inputElem = from.localMediaElements[0];
+ let localTransceivers = this._pc.getTransceivers()
+ .filter(t => t.mid)
+ .filter(t => t.receiver.track.kind == "audio")
+ .sort((t1, t2) => t1.mid < t2.mid);
+ let remoteTransceivers = from._pc.getTransceivers()
+ .filter(t => t.mid)
+ .filter(t => t.receiver.track.kind == "audio")
+ .sort((t1, t2) => t1.mid < t2.mid);
- // As input we use the stream of |from|'s first available audio sender.
- let inputSenderTracks = from._pc.getSenders().map(sn => sn.track);
- let inputAudioStream = from._pc.getLocalStreams()
- .find(s => inputSenderTracks.some(t => t.kind == "audio" && s.getTrackById(t.id)));
- let inputAnalyser = new AudioStreamAnalyser(audiocontext, inputAudioStream);
+ is(localTransceivers.length, remoteTransceivers.length,
+ "Same number of associated audio transceivers on remote and local.");
- // It would have been nice to have a working getReceivers() here, but until
- // we do, let's use what remote streams we have.
- let outputAudioStream = this._pc.getRemoteStreams()
- .find(s => s.getAudioTracks().length > 0);
- let outputAnalyser = new AudioStreamAnalyser(audiocontext, outputAudioStream);
+ for (let i = 0; i < localTransceivers.length; i++) {
+ is(localTransceivers[i].mid, remoteTransceivers[i].mid,
+ "Transceivers at index " + i + " have the same mid.");
- let error = null;
- cancel.then(e => error = e);
+ if (!remoteTransceivers[i].sender.track) {
+ continue;
+ }
- let indexOfMax = data =>
- data.reduce((max, val, i) => (val >= data[max]) ? i : max, 0);
-
- await outputAnalyser.waitForAnalysisSuccess(() => {
- if (error) {
- throw error;
+ if (remoteTransceivers[i].currentDirection == "recvonly" ||
+ remoteTransceivers[i].currentDirection == "inactive") {
+ continue;
}
- let inputData = inputAnalyser.getByteFrequencyData();
- let outputData = outputAnalyser.getByteFrequencyData();
+ let sendTrack = remoteTransceivers[i].sender.track;
+ let inputElem = from.getMediaElementForTrack(sendTrack, "local");
+ ok(inputElem,
+ "Remote wrapper should have a media element for track id " +
+ sendTrack.id);
+ let inputAudioStream = from.getStreamForSendTrack(sendTrack);
+ ok(inputAudioStream,
+ "Remote wrapper should have a stream for track id " + sendTrack.id);
+ let inputAnalyser =
+ new AudioStreamAnalyser(audiocontext, inputAudioStream);
+
+ let recvTrack = localTransceivers[i].receiver.track;
+ let outputAudioStream = this.getStreamForRecvTrack(recvTrack);
+ ok(outputAudioStream,
+ "Local wrapper should have a stream for track id " + recvTrack.id);
+ let outputAnalyser =
+ new AudioStreamAnalyser(audiocontext, outputAudioStream);
+
+ let error = null;
+ cancel.then(e => error = e);
+
+ let indexOfMax = data =>
+ data.reduce((max, val, i) => (val >= data[max]) ? i : max, 0);
- let inputMax = indexOfMax(inputData);
- let outputMax = indexOfMax(outputData);
- info(`Comparing maxima; input[${inputMax}] = ${inputData[inputMax]},`
- + ` output[${outputMax}] = ${outputData[outputMax]}`);
- if (!inputData[inputMax] || !outputData[outputMax]) {
- return false;
- }
+ await outputAnalyser.waitForAnalysisSuccess(() => {
+ if (error) {
+ throw error;
+ }
+
+ let inputData = inputAnalyser.getByteFrequencyData();
+ let outputData = outputAnalyser.getByteFrequencyData();
- // When the input and output maxima are within reasonable distance (2% of
- // total length, which means ~10 for length 512) from each other, we can
- // be sure that the input tone has made it through the peer connection.
- info(`input data length: ${inputData.length}`);
- return Math.abs(inputMax - outputMax) < (inputData.length * 0.02);
- });
+ let inputMax = indexOfMax(inputData);
+ let outputMax = indexOfMax(outputData);
+ info(`Comparing maxima; input[${inputMax}] = ${inputData[inputMax]},`
+ + ` output[${outputMax}] = ${outputData[outputMax]}`);
+ if (!inputData[inputMax] || !outputData[outputMax]) {
+ return false;
+ }
+
+ // When the input and output maxima are within reasonable distance (2% of
+ // total length, which means ~10 for length 512) from each other, we can
+ // be sure that the input tone has made it through the peer connection.
+ info(`input data length: ${inputData.length}`);
+ return Math.abs(inputMax - outputMax) < (inputData.length * 0.02);
+ });
+ }
},
/**
* Get stats from the "legacy" getStats callback interface
*/
getStatsLegacy : function(selector, onSuccess, onFail) {
let wrapper = stats => {
info(this + ": Got legacy stats: " + JSON.stringify(stats));
@@ -1617,16 +1770,17 @@ PeerConnectionWrapper.prototype = {
* The stats to check from this PeerConnectionWrapper
*/
checkStats : function(stats, twoMachines) {
const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
// Use spec way of enumerating stats
var counters = {};
for (let [key, res] of stats) {
+ info("Checking stats for " + key + " : " + res);
// validate stats
ok(res.id == key, "Coherent stats id");
var nowish = Date.now() + 1000; // TODO: clock drift observed
var minimum = this.whenCreated - 1000; // on Windows XP (Bug 979649)
if (isWinXP) {
todo(false, "Can't reliably test rtcp timestamps on WinXP (Bug 979649)");
} else if (false) { // Bug 1325430 - timestamps aren't working properly in update 49
@@ -1650,21 +1804,27 @@ PeerConnectionWrapper.prototype = {
if (res.isRemote) {
continue;
}
counters[res.type] = (counters[res.type] || 0) + 1;
switch (res.type) {
case "inbound-rtp":
case "outbound-rtp": {
- // ssrc is a 32 bit number returned as a string by spec
- ok(res.ssrc.length > 0, "Ssrc has length");
- ok(res.ssrc.length < 11, "Ssrc not lengthy");
- ok(!/[^0-9]/.test(res.ssrc), "Ssrc numeric");
- ok(parseInt(res.ssrc) < Math.pow(2,32), "Ssrc within limits");
+ // Inbound tracks won't have an ssrc if RTP is not flowing.
+ // (eg; negotiated inactive)
+ ok(res.ssrc || res.type == "inbound-rtp", "Outbound RTP stats has an ssrc.");
+
+ if (res.ssrc) {
+ // ssrc is a 32 bit number returned as a string by spec
+ ok(res.ssrc.length > 0, "Ssrc has length");
+ ok(res.ssrc.length < 11, "Ssrc not lengthy");
+ ok(!/[^0-9]/.test(res.ssrc), "Ssrc numeric");
+ ok(parseInt(res.ssrc) < Math.pow(2,32), "Ssrc within limits");
+ }
if (res.type == "outbound-rtp") {
ok(res.packetsSent !== undefined, "Rtp packetsSent");
// We assume minimum payload to be 1 byte (guess from RFC 3550)
ok(res.bytesSent >= res.packetsSent, "Rtp bytesSent");
} else {
ok(res.packetsReceived !== undefined, "Rtp packetsReceived");
ok(res.bytesReceived >= res.packetsReceived, "Rtp bytesReceived");
@@ -1729,17 +1889,22 @@ PeerConnectionWrapper.prototype = {
var res = stats[key];
var type = legacyToSpecMapping[res.type] || res.type;
if (!res.isRemote) {
counters2[type] = (counters2[type] || 0) + 1;
}
}
is(JSON.stringify(counters), JSON.stringify(counters2),
"Spec and legacy variant of RTCStatsReport enumeration agree");
- var nin = Object.keys(this.expectedRemoteTrackInfoById).length;
+ var nin = this._pc.getTransceivers()
+ .filter(t => {
+ return !t.stopped &&
+ (t.currentDirection != "inactive") &&
+ (t.currentDirection != "sendonly");
+ }).length;
var nout = Object.keys(this.expectedLocalTrackInfoById).length;
var ndata = this.dataChannels.length;
// TODO(Bug 957145): Restore stronger inbound-rtp test once Bug 948249 is fixed
//is((counters["inbound-rtp"] || 0), nin, "Have " + nin + " inbound-rtp stat(s)");
ok((counters["inbound-rtp"] || 0) >= nin, "Have at least " + nin + " inbound-rtp stat(s) *");
is(counters["outbound-rtp"] || 0, nout, "Have " + nout + " outbound-rtp stat(s)");
@@ -1805,49 +1970,46 @@ PeerConnectionWrapper.prototype = {
/**
* Compares amount of established ICE connection according to ICE candidate
* pairs in the stats reporting with the expected amount of connection based
* on the constraints.
*
* @param {object} stats
* The stats to check for ICE candidate pairs
- * @param {object} counters
- * The counters for media and data tracks based on constraints
* @param {object} testOptions
* The test options object from the PeerConnectionTest
*/
- checkStatsIceConnections : function(stats,
- offerConstraintsList, offerOptions, testOptions) {
+ checkStatsIceConnections : function(stats, testOptions) {
var numIceConnections = 0;
stats.forEach(stat => {
if ((stat.type === "candidate-pair") && stat.selected) {
numIceConnections += 1;
}
});
info("ICE connections according to stats: " + numIceConnections);
isnot(numIceConnections, 0, "Number of ICE connections according to stats is not zero");
if (testOptions.bundle) {
if (testOptions.rtcpmux) {
is(numIceConnections, 1, "stats reports exactly 1 ICE connection");
} else {
is(numIceConnections, 2, "stats report exactly 2 ICE connections for media and RTCP");
}
} else {
- // This code assumes that no media sections have been rejected due to
- // codec mismatch or other unrecoverable negotiation failures.
- var numAudioTracks =
- sdputils.countTracksInConstraint('audio', offerConstraintsList) ||
- ((offerOptions && offerOptions.offerToReceiveAudio) ? 1 : 0);
+ var numAudioTransceivers =
+ this._pc.getTransceivers().filter((transceiver) => {
+ return (!transceiver.stopped) && transceiver.receiver.track.kind == "audio";
+ }).length;
- var numVideoTracks =
- sdputils.countTracksInConstraint('video', offerConstraintsList) ||
- ((offerOptions && offerOptions.offerToReceiveVideo) ? 1 : 0);
+ var numVideoTransceivers =
+ this._pc.getTransceivers().filter((transceiver) => {
+ return (!transceiver.stopped) && transceiver.receiver.track.kind == "video";
+ }).length;
- var numExpectedTransports = numAudioTracks + numVideoTracks;
+ var numExpectedTransports = numAudioTransceivers + numVideoTransceivers;
if (!testOptions.rtcpmux) {
numExpectedTransports *= 2;
}
if (this.dataChannels.length) {
++numExpectedTransports;
}
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -78,18 +78,17 @@ function waitForAnIceCandidate(pc) {
}).then(() => {
ok(pc._local_ice_candidates.length > 0,
pc + " received local trickle ICE candidates");
isnot(pc._pc.iceGatheringState, GATH_NEW,
pc + " ICE gathering state is not 'new'");
});
}
-function checkTrackStats(pc, rtpSenderOrReceiver, outbound) {
- var track = rtpSenderOrReceiver.track;
+function checkTrackStats(pc, track, outbound) {
var audio = (track.kind == "audio");
var msg = pc + " stats " + (outbound ? "outbound " : "inbound ") +
(audio ? "audio" : "video") + " rtp track id " + track.id;
return pc.getStats(track).then(stats => {
ok(pc.hasStat(stats, {
type: outbound ? "outbound-rtp" : "inbound-rtp",
isRemote: false,
mediaType: audio ? "audio" : "video"
@@ -101,18 +100,18 @@ function checkTrackStats(pc, rtpSenderOr
ok(!pc.hasStat(stats, {
mediaType: audio ? "video" : "audio"
}), msg + " - did not find extra stats with wrong media type");
});
}
var checkAllTrackStats = pc => {
return Promise.all([].concat(
- pc._pc.getSenders().map(sender => checkTrackStats(pc, sender, true)),
- pc._pc.getReceivers().map(receiver => checkTrackStats(pc, receiver, false))));
+ pc.getExpectedActiveReceiveTracks().map(track => checkTrackStats(pc, track, false)),
+ pc.getExpectedSendTracks().map(track => checkTrackStats(pc, track, true))));
}
// Commands run once at the beginning of each test, even when performing a
// renegotiation test.
var commandsPeerConnectionInitial = [
function PC_SETUP_SIGNALING_CLIENT(test) {
if (test.testOptions.steeplechase) {
test.setupSignalingClient();
@@ -178,21 +177,21 @@ var commandsPeerConnectionInitial = [
function PC_REMOTE_CHECK_INITIAL_CAN_TRICKLE_SYNC(test) {
is(test.pcRemote._pc.canTrickleIceCandidates, null,
"Remote trickle status should start out unknown");
},
];
var commandsGetUserMedia = [
function PC_LOCAL_GUM(test) {
- return test.pcLocal.getAllUserMedia(test.pcLocal.constraints);
+ return test.pcLocal.getAllUserMediaAndAddStreams(test.pcLocal.constraints);
},
function PC_REMOTE_GUM(test) {
- return test.pcRemote.getAllUserMedia(test.pcRemote.constraints);
+ return test.pcRemote.getAllUserMediaAndAddStreams(test.pcRemote.constraints);
},
];
var commandsPeerConnectionOfferAnswer = [
function PC_LOCAL_SETUP_ICE_HANDLER(test) {
test.pcLocal.setupIceCandidateHandler(test);
},
@@ -209,42 +208,16 @@ var commandsPeerConnectionOfferAnswer =
function PC_REMOTE_STEEPLECHASE_SIGNAL_EXPECTED_LOCAL_TRACKS(test) {
if (test.testOptions.steeplechase) {
send_message({"type": "remote_expected_tracks",
"expected_tracks": test.pcRemote.expectedLocalTrackInfoById});
}
},
- function PC_LOCAL_GET_EXPECTED_REMOTE_TRACKS(test) {
- if (test.testOptions.steeplechase) {
- return test.getSignalingMessage("remote_expected_tracks").then(
- message => {
- test.pcLocal.expectedRemoteTrackInfoById = message.expected_tracks;
- });
- }
-
- // Deep copy, as similar to steeplechase as possible
- test.pcLocal.expectedRemoteTrackInfoById =
- JSON.parse(JSON.stringify(test.pcRemote.expectedLocalTrackInfoById));
- },
-
- function PC_REMOTE_GET_EXPECTED_REMOTE_TRACKS(test) {
- if (test.testOptions.steeplechase) {
- return test.getSignalingMessage("local_expected_tracks").then(
- message => {
- test.pcRemote.expectedRemoteTrackInfoById = message.expected_tracks;
- });
- }
-
- // Deep copy, as similar to steeplechase as possible
- test.pcRemote.expectedRemoteTrackInfoById =
- JSON.parse(JSON.stringify(test.pcLocal.expectedLocalTrackInfoById));
- },
-
function PC_LOCAL_CREATE_OFFER(test) {
return test.createOffer(test.pcLocal).then(offer => {
is(test.pcLocal.signalingState, STABLE,
"Local create offer does not change signaling state");
});
},
function PC_LOCAL_STEEPLECHASE_SIGNAL_OFFER(test) {
@@ -430,29 +403,23 @@ var commandsPeerConnectionOfferAnswer =
return test.pcRemote.getStats().then(stats => {
test.pcRemote.checkStatsIceConnectionType(stats,
test.testOptions.expectedRemoteCandidateType);
});
},
function PC_LOCAL_CHECK_ICE_CONNECTIONS(test) {
return test.pcLocal.getStats().then(stats => {
- test.pcLocal.checkStatsIceConnections(stats,
- test._offer_constraints,
- test._offer_options,
- test.testOptions);
+ test.pcLocal.checkStatsIceConnections(stats, test.testOptions);
});
},
function PC_REMOTE_CHECK_ICE_CONNECTIONS(test) {
return test.pcRemote.getStats().then(stats => {
- test.pcRemote.checkStatsIceConnections(stats,
- test._offer_constraints,
- test._offer_options,
- test.testOptions);
+ test.pcRemote.checkStatsIceConnections(stats, test.testOptions);
});
},
function PC_LOCAL_CHECK_MSID(test) {
return test.pcLocal.checkMsids();
},
function PC_REMOTE_CHECK_MSID(test) {
return test.pcRemote.checkMsids();
--- a/dom/media/tests/mochitest/test_peerConnection_addSecondAudioStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addSecondAudioStream.html
@@ -13,17 +13,17 @@
runNetworkTest(function (options) {
const test = new PeerConnectionTest(options);
addRenegotiation(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}]);
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
],
[
function PC_REMOTE_CHECK_ADDED_TRACK(test) {
// We test both tracks to avoid an ordering problem
is(test.pcRemote._pc.getReceivers().length, 2,
"pcRemote should have two receivers");
return Promise.all(test.pcRemote._pc.getReceivers().map(r => {
--- a/dom/media/tests/mochitest/test_peerConnection_addSecondAudioStreamNoBundle.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addSecondAudioStreamNoBundle.html
@@ -17,17 +17,17 @@
addRenegotiation(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}]);
// Since this is a NoBundle variant, adding a track will cause us to
// go back to checking.
test.pcLocal.expectIceChecking();
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
test.pcRemote.expectIceChecking();
},
],
[
function PC_REMOTE_CHECK_ADDED_TRACK(test) {
// We test both tracks to avoid an ordering problem
--- a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStream.html
@@ -16,17 +16,17 @@
const test = new PeerConnectionTest(options);
addRenegotiation(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{video: true}, {video: true}],
[{video: true}]);
// Use fake:true here since the native fake device on linux doesn't
// change color as needed by checkVideoPlaying() below.
- return test.pcLocal.getAllUserMedia([{video: true, fake: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]);
},
],
[
function PC_REMOTE_CHECK_VIDEO_FLOW(test) {
const h = new VideoStreamHelper();
is(test.pcRemote.remoteMediaElements.length, 2,
"Should have two remote media elements after renegotiation");
return Promise.all(test.pcRemote.remoteMediaElements.map(video =>
--- a/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html
@@ -20,17 +20,17 @@
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{video: true}, {video: true}],
[{video: true}]);
// Since this is a NoBundle variant, adding a track will cause us to
// go back to checking.
test.pcLocal.expectIceChecking();
// Use fake:true here since the native fake device on linux doesn't
// change color as needed by checkVideoPlaying() below.
- return test.pcLocal.getAllUserMedia([{video: true, fake: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]);
},
function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
test.pcRemote.expectIceChecking();
},
],
[
function PC_REMOTE_CHECK_VIDEO_FLOW(test) {
const h = new VideoStreamHelper();
--- a/dom/media/tests/mochitest/test_peerConnection_addtrack_removetrack_events.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addtrack_removetrack_events.html
@@ -15,53 +15,54 @@ createHTML({
runNetworkTest(function (options) {
let test = new PeerConnectionTest(options);
let eventsPromise;
addRenegotiation(test.chain,
[
function PC_LOCAL_SWAP_VIDEO_TRACKS(test) {
return getUserMedia({video: true}).then(stream => {
+ var videoTransceiver = test.pcLocal._pc.getTransceivers()[1];
+ is(videoTransceiver.currentDirection, "sendonly",
+ "Video transceiver's current direction is sendonly");
+ is(videoTransceiver.direction, "sendrecv",
+ "Video transceiver's desired direction is sendrecv");
+
const localStream = test.pcLocal._pc.getLocalStreams()[0];
ok(localStream, "Should have local stream");
const remoteStream = test.pcRemote._pc.getRemoteStreams()[0];
ok(remoteStream, "Should have remote stream");
const newTrack = stream.getTracks()[0];
const videoSenderIndex =
test.pcLocal._pc.getSenders().findIndex(s => s.track.kind == "video");
isnot(videoSenderIndex, -1, "Should have video sender");
test.pcLocal.removeSender(videoSenderIndex);
+ is(videoTransceiver.direction, "recvonly",
+ "Video transceiver should be recvonly after removeTrack");
test.pcLocal.attachLocalTrack(stream.getTracks()[0], localStream);
+ is(videoTransceiver.direction, "recvonly",
+ "Video transceiver should be recvonly after addTrack");
- const addTrackPromise = haveEvent(remoteStream, "addtrack",
- wait(50000, new Error("No addtrack event")))
+ eventsPromise = haveEvent(remoteStream, "addtrack",
+ wait(50000, new Error("No addtrack event for " + newTrack.id)))
.then(trackEvent => {
ok(trackEvent instanceof MediaStreamTrackEvent,
"Expected event to be instance of MediaStreamTrackEvent");
is(trackEvent.type, "addtrack",
"Expected addtrack event type");
- is(trackEvent.track.id, newTrack.id, "Expected track in event");
+ is(test.pcRemote.getWebrtcTrackId(trackEvent.track), newTrack.id, "Expected track in event");
is(trackEvent.track.readyState, "live",
"added track should be live");
})
.then(() => haveNoEvent(remoteStream, "addtrack"));
- const remoteTrack = test.pcRemote._pc.getReceivers()
- .map(r => r.track)
- .find(t => t.kind == "video");
- ok(remoteTrack, "Should have received remote track");
- const endedPromise = haveEvent(remoteTrack, "ended",
- wait(50000, new Error("No ended event")));
-
- eventsPromise = Promise.all([addTrackPromise, endedPromise]);
-
remoteStream.addEventListener("removetrack",
function onRemovetrack(trackEvent) {
ok(false, "UA shouldn't raise 'removetrack' when receiving peer connection");
})
});
},
],
[
--- a/dom/media/tests/mochitest/test_peerConnection_answererAddSecondAudioStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_answererAddSecondAudioStream.html
@@ -14,17 +14,17 @@
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addRenegotiationAnswerer(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}]);
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
]
);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
});
</script>
--- a/dom/media/tests/mochitest/test_peerConnection_bug1064223.html
+++ b/dom/media/tests/mochitest/test_peerConnection_bug1064223.html
@@ -11,17 +11,17 @@
title: "CreateOffer fails without streams or modern RTCOfferOptions"
});
runNetworkTest(function () {
var pc = new mozRTCPeerConnection();
var options = { mandatory: { OfferToReceiveVideo: true } }; // obsolete
pc.createOffer(options).then(() => ok(false, "createOffer must fail"),
- e => is(e.name, "InternalError",
+ e => is(e.name, "InvalidStateError",
"createOffer must fail"))
.catch(e => ok(false, e.message))
.then(() => {
pc.close();
networkTestFinished();
})
.catch(e => ok(false, e.message));
});
--- a/dom/media/tests/mochitest/test_peerConnection_constructedStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_constructedStream.html
@@ -45,17 +45,17 @@ runNetworkTest(() => {
ok(receivedStream, "We should receive a stream with with the sent stream's id (" + sentStreamId + ")");
if (!receivedStream) {
return;
}
is(receivedStream.getTracks().length, sentTracks.length,
"Should receive same number of tracks as were sent");
sentTracks.forEach(t =>
- ok(receivedStream.getTracks().find(t2 => t.id == t2.id),
+ ok(receivedStream.getTracks().find(t2 => t.id == test.pcRemote.getWebrtcTrackId(t2)),
"The sent track (" + t.id + ") should exist on the receive side"));
};
test.chain.append([
function PC_REMOTE_CHECK_RECEIVED_CONSTRUCTED_STREAM() {
checkSentTracksReceived(constructedStream.id, constructedStream.getTracks());
},
function PC_REMOTE_CHECK_RECEIVED_DUMMY_STREAM() {
--- a/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html
@@ -13,17 +13,17 @@
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addRenegotiation(test.chain, [
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}]);
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
function PC_REMOTE_SETUP_ICE_HANDLER(test) {
test.pcRemote.setupIceCandidateHandler(test);
if (test.testOptions.steeplechase) {
test.pcRemote.endOfTrickleIce.then(() => {
send_message({"type": "end_of_trickle_ice"});
});
@@ -32,16 +32,19 @@
function PC_REMOTE_CREATE_AND_SET_OFFER(test) {
return test.createOffer(test.pcRemote).then(offer => {
return test.setLocalDescription(test.pcRemote, offer, HAVE_LOCAL_OFFER);
});
},
function PC_REMOTE_ROLLBACK(test) {
+ // the negotiationNeeded slot should have been true both before and
+ // after this SLD, so the event should fire again.
+ test.pcRemote.expectNegotiationNeeded();
return test.setLocalDescription(test.pcRemote,
{ type: "rollback", sdp: "" },
STABLE);
},
// Rolling back should shut down gathering
function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) {
return test.pcRemote.endOfTrickleIce;
--- a/dom/media/tests/mochitest/test_peerConnection_localRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_localRollback.html
@@ -18,16 +18,19 @@
test.chain.insertBefore('PC_LOCAL_CREATE_OFFER', [
function PC_REMOTE_CREATE_AND_SET_OFFER(test) {
return test.createOffer(test.pcRemote).then(offer => {
return test.setLocalDescription(test.pcRemote, offer, HAVE_LOCAL_OFFER);
});
},
function PC_REMOTE_ROLLBACK(test) {
+ // the negotiationNeeded slot should have been true both before and
+ // after this SLD, so the event should fire again.
+ test.pcRemote.expectNegotiationNeeded();
return test.setLocalDescription(test.pcRemote,
{ type: "rollback", sdp: "" },
STABLE);
},
// Rolling back should shut down gathering
function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) {
return test.pcRemote.endOfTrickleIce;
--- a/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html
+++ b/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html
@@ -14,17 +14,17 @@
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
addRenegotiation(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}]);
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
]
);
test.chain.replaceAfter('PC_REMOTE_SET_REMOTE_DESCRIPTION',
[
function PC_LOCAL_SETUP_ICE_HANDLER(test) {
test.pcLocal.setupIceCandidateHandler(test);
if (test.testOptions.steeplechase) {
--- a/dom/media/tests/mochitest/test_peerConnection_removeAudioTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeAudioTrack.html
@@ -32,20 +32,21 @@
},
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
test.setOfferOptions({ offerToReceiveAudio: true });
return test.pcLocal.removeSender(0);
},
],
[
function PC_REMOTE_CHECK_FLOW_STOPPED(test) {
- is(test.pcRemote._pc.getReceivers().length, 0,
- "pcRemote should have no more receivers");
- is(receivedTrack.readyState, "ended",
- "The received track should have ended");
+ // Simply removing a track is not enough to cause it to be
+ // signaled as ended. Spec may change though.
+ // TODO: One last check of the spec is in order
+ is(receivedTrack.readyState, "live",
+ "The received track should not have ended");
return analyser.waitForAnalysisSuccess(arr => arr[freq] < 50);
},
]
);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
--- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddAudioTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddAudioTrack.html
@@ -24,31 +24,40 @@
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
return test.pcLocal.removeSender(0);
},
function PC_LOCAL_ADD_AUDIO_TRACK(test) {
// The new track's pipeline will start with a packet count of
// 0, but the remote side will keep its old pipeline and packet
// count.
test.pcLocal.disableRtpCountChecking = true;
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
],
[
function PC_REMOTE_CHECK_ADDED_TRACK(test) {
- is(test.pcRemote._pc.getReceivers().length, 1,
- "pcRemote should still have one receiver");
- const track = test.pcRemote._pc.getReceivers()[0].track;
- isnot(originalTrack.id, track.id, "Receiver should have changed");
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[1].receiver.track;
const analyser = new AudioStreamAnalyser(
new AudioContext(), new MediaStream([track]));
const freq = analyser.binIndexForFrequency(TEST_AUDIO_FREQ);
return analyser.waitForAnalysisSuccess(arr => arr[freq] > 200);
},
+ function PC_REMOTE_CHECK_REMOVED_TRACK(test) {
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[0].receiver.track;
+
+ const analyser = new AudioStreamAnalyser(
+ new AudioContext(), new MediaStream([track]));
+ const freq = analyser.binIndexForFrequency(TEST_AUDIO_FREQ);
+ return analyser.waitForAnalysisSuccess(arr => arr[freq] < 50);
+ }
]
);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
});
</script>
</pre>
--- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddAudioTrackNoBundle.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddAudioTrackNoBundle.html
@@ -7,16 +7,18 @@
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1017888",
title: "Renegotiation: remove then add audio track"
});
runNetworkTest(function (options) {
+ options = options || { };
+ options.bundle = false;
const test = new PeerConnectionTest(options);
let originalTrack;
addRenegotiation(test.chain,
[
function PC_REMOTE_FIND_RECEIVER(test) {
is(test.pcRemote._pc.getReceivers().length, 1,
"pcRemote should have one receiver");
originalTrack = test.pcRemote._pc.getReceivers()[0].track;
@@ -24,31 +26,46 @@
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
// The new track's pipeline will start with a packet count of
// 0, but the remote side will keep its old pipeline and packet
// count.
test.pcLocal.disableRtpCountChecking = true;
return test.pcLocal.removeSender(0);
},
function PC_LOCAL_ADD_AUDIO_TRACK(test) {
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
+ },
+ function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
+ test.pcLocal.expectIceChecking();
+ },
+ function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
+ test.pcRemote.expectIceChecking();
},
],
[
function PC_REMOTE_CHECK_ADDED_TRACK(test) {
- is(test.pcRemote._pc.getReceivers().length, 1,
- "pcRemote should still have one receiver");
- const track = test.pcRemote._pc.getReceivers()[0].track;
- isnot(originalTrack.id, track.id, "Receiver should have changed");
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[1].receiver.track;
const analyser = new AudioStreamAnalyser(
new AudioContext(), new MediaStream([track]));
const freq = analyser.binIndexForFrequency(TEST_AUDIO_FREQ);
return analyser.waitForAnalysisSuccess(arr => arr[freq] > 200);
},
+ function PC_REMOTE_CHECK_REMOVED_TRACK(test) {
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[0].receiver.track;
+
+ const analyser = new AudioStreamAnalyser(
+ new AudioContext(), new MediaStream([track]));
+ const freq = analyser.binIndexForFrequency(TEST_AUDIO_FREQ);
+ return analyser.waitForAnalysisSuccess(arr => arr[freq] < 50);
+ }
]
);
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
--- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrack.html
@@ -28,33 +28,38 @@
// 0, but the remote side will keep its old pipeline and packet
// count.
test.pcLocal.disableRtpCountChecking = true;
return test.pcLocal.removeSender(0);
},
function PC_LOCAL_ADD_VIDEO_TRACK(test) {
// Use fake:true here since the native fake device on linux doesn't
// change color as needed by checkVideoPlaying() below.
- return test.pcLocal.getAllUserMedia([{video: true, fake: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]);
},
],
[
function PC_REMOTE_CHECK_ADDED_TRACK(test) {
- is(test.pcRemote._pc.getReceivers().length, 1,
- "pcRemote should still have one receiver");
- const track = test.pcRemote._pc.getReceivers()[0].track;
- isnot(originalTrack.id, track.id, "Receiver should have changed");
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[1].receiver.track;
- const vOriginal = test.pcRemote.remoteMediaElements.find(
- elem => elem.id.includes(originalTrack.id));
const vAdded = test.pcRemote.remoteMediaElements.find(
elem => elem.id.includes(track.id));
- ok(vOriginal.ended, "Original video element should have ended");
return helper.checkVideoPlaying(vAdded);
},
+ function PC_REMOTE_CHECK_REMOVED_TRACK(test) {
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[0].receiver.track;
+
+ const vAdded = test.pcRemote.remoteMediaElements.find(
+ elem => elem.id.includes(track.id));
+ return helper.checkVideoPaused(vAdded, 10, 10, 16, 5000);
+ }
]
);
test.setMediaConstraints([{video: true}], [{video: true}]);
test.run();
});
</script>
</pre>
--- a/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeThenAddVideoTrackNoBundle.html
@@ -8,16 +8,18 @@
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1017888",
title: "Renegotiation: remove then add video track, no bundle"
});
runNetworkTest(function (options) {
+ options = options || { };
+ options.bundle = false;
const test = new PeerConnectionTest(options);
const helper = new VideoStreamHelper();
var originalTrack;
addRenegotiation(test.chain,
[
function PC_REMOTE_FIND_RECEIVER(test) {
is(test.pcRemote._pc.getReceivers().length, 1,
"pcRemote should have one receiver");
@@ -28,33 +30,44 @@
// 0, but the remote side will keep its old pipeline and packet
// count.
test.pcLocal.disableRtpCountChecking = true;
return test.pcLocal.removeSender(0);
},
function PC_LOCAL_ADD_VIDEO_TRACK(test) {
// Use fake:true here since the native fake device on linux doesn't
// change color as needed by checkVideoPlaying() below.
- return test.pcLocal.getAllUserMedia([{video: true, fake: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{video: true, fake: true}]);
+ },
+ function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
+ test.pcLocal.expectIceChecking();
+ },
+ function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
+ test.pcRemote.expectIceChecking();
},
],
[
function PC_REMOTE_CHECK_ADDED_TRACK(test) {
- is(test.pcRemote._pc.getReceivers().length, 1,
- "pcRemote should still have one receiver");
- const track = test.pcRemote._pc.getReceivers()[0].track;
- isnot(originalTrack.id, track.id, "Receiver should have changed");
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[1].receiver.track;
- const vOriginal = test.pcRemote.remoteMediaElements.find(
- elem => elem.id.includes(originalTrack.id));
const vAdded = test.pcRemote.remoteMediaElements.find(
elem => elem.id.includes(track.id));
- ok(vOriginal.ended, "Original video element should have ended");
return helper.checkVideoPlaying(vAdded);
},
+ function PC_REMOTE_CHECK_REMOVED_TRACK(test) {
+ is(test.pcRemote._pc.getTransceivers().length, 2,
+ "pcRemote should have two transceivers");
+ const track = test.pcRemote._pc.getTransceivers()[0].receiver.track;
+
+ const vAdded = test.pcRemote.remoteMediaElements.find(
+ elem => elem.id.includes(track.id));
+ return helper.checkVideoPaused(vAdded, 10, 10, 16, 5000);
+ },
]
);
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
test.setMediaConstraints([{video: true}], [{video: true}]);
test.run();
--- a/dom/media/tests/mochitest/test_peerConnection_removeVideoTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_removeVideoTrack.html
@@ -1,12 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
+ <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1017888",
title: "Renegotiation: remove video track"
});
@@ -31,22 +32,24 @@
function PC_LOCAL_REMOVE_VIDEO_TRACK(test) {
test.setOfferOptions({ offerToReceiveVideo: true });
test.setMediaConstraints([], [{video: true}]);
return test.pcLocal.removeSender(0);
},
],
[
function PC_REMOTE_CHECK_FLOW_STOPPED(test) {
- is(test.pcRemote._pc.getReceivers().length, 0,
- "pcRemote should have no more receivers");
- is(receivedTrack.readyState, "ended",
- "The received track should have ended");
- is(element.ended, true,
- "Element playing the removed track should have ended");
+ is(test.pcRemote._pc.getTransceivers().length, 1,
+ "pcRemote should have one transceiver");
+ const track = test.pcRemote._pc.getTransceivers()[0].receiver.track;
+
+ const vAdded = test.pcRemote.remoteMediaElements.find(
+ elem => elem.id.includes(track.id));
+ const helper = new VideoStreamHelper();
+ return helper.checkVideoPaused(vAdded, 10, 10, 16, 5000);
},
]
);
test.setMediaConstraints([{video: true}], [{video: true}]);
test.run();
});
</script>
--- a/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html
+++ b/dom/media/tests/mochitest/test_peerConnection_replaceTrack.html
@@ -42,29 +42,31 @@
return navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(newStream => {
window.grip = newStream;
newTrack = newStream.getVideoTracks()[0];
audiotrack = newStream.getAudioTracks()[0];
isnot(newTrack, sender.track, "replacing with a different track");
ok(!pc.getLocalStreams().some(s => s == newStream),
"from a different stream");
- return sender.replaceTrack(newTrack);
+ // Use wrapper function, since it updates expected tracks
+ return wrapper.senderReplaceTrack(sender, newTrack, newStream);
})
.then(() => {
is(pc.getSenders().length, oldSenderCount, "same sender count");
is(sender.track, newTrack, "sender.track has been replaced");
ok(!pc.getSenders().map(sn => sn.track).some(t => t == oldTrack),
"old track not among senders");
- ok(pc.getLocalStreams().some(s => s.getTracks()
+ // Spec does not say we add this new track to any stream
+ ok(!pc.getLocalStreams().some(s => s.getTracks()
.some(t => t == sender.track)),
- "track exists among pc's local streams");
+ "track does not exist among pc's local streams");
return sender.replaceTrack(audiotrack)
.then(() => ok(false, "replacing with different kind should fail"),
- e => is(e.name, "IncompatibleMediaStreamTrackError",
+ e => is(e.name, "TypeError",
"replacing with different kind should fail"));
});
}
runNetworkTest(function () {
test = new PeerConnectionTest();
test.audioCtx = new AudioContext();
test.setMediaConstraints([{video: true, audio: true}], [{video: true}]);
@@ -125,53 +127,61 @@
// (440Hz for loopback devices, 1kHz for fake tracks).
sourceNode.frequency.value = 2000;
sourceNode.start();
var destNode = test.audioCtx.createMediaStreamDestination();
sourceNode.connect(destNode);
var newTrack = destNode.stream.getAudioTracks()[0];
- return sender.replaceTrack(newTrack)
+ return test.pcLocal.senderReplaceTrack(
+ sender, newTrack, destNode.stream)
.then(() => {
is(pc.getSenders().length, oldSenderCount, "same sender count");
ok(!pc.getSenders().some(sn => sn.track == oldTrack),
"Replaced track should be removed from senders");
- ok(allLocalStreamsHaveSender(pc),
- "Shouldn't have any streams without a corresponding sender");
+ // TODO: Should PC remove local streams when there are no senders
+ // associated with it? getLocalStreams() isn't in the spec anymore,
+ // so I guess it is pretty arbitrary?
is(sender.track, newTrack, "sender.track has been replaced");
- ok(pc.getLocalStreams().some(s => s.getTracks()
+ // Spec does not say we add this new track to any stream
+ ok(!pc.getLocalStreams().some(s => s.getTracks()
.some(t => t == sender.track)),
"track exists among pc's local streams");
});
}
]);
test.chain.append([
function PC_LOCAL_CHECK_WEBAUDIO_FLOW_PRESENT(test) {
return test.pcRemote.checkReceivingToneFrom(test.audioCtx, test.pcLocal);
}
]);
test.chain.append([
function PC_LOCAL_INVALID_ADD_VIDEOTRACKS(test) {
- var stream = test.pcLocal._pc.getLocalStreams()[0];
- var track = stream.getVideoTracks()[0];
- try {
- test.pcLocal._pc.addTrack(track, stream);
- ok(false, "addTrack existing track should fail");
- } catch (e) {
- is(e.name, "InvalidParameterError",
- "addTrack existing track should fail");
- }
- try {
- test.pcLocal._pc.addTrack(track, stream);
- ok(false, "addTrack existing track should fail");
- } catch (e) {
- is(e.name, "InvalidParameterError",
- "addTrack existing track should fail");
- }
+ let videoTransceivers = test.pcLocal._pc.getTransceivers()
+ .filter(transceiver => {
+ return !transceiver.stopped &&
+ transceiver.receiver.track.kind == "video" &&
+ transceiver.sender.track;
+ });
+
+ ok(videoTransceivers.length,
+ "There is at least one non-stopped video transceiver with a track.");
+
+ videoTransceivers.forEach(transceiver => {
+ var stream = test.pcLocal._pc.getLocalStreams()[0];;
+ var track = transceiver.sender.track;
+ try {
+ test.pcLocal._pc.addTrack(track, stream);
+ ok(false, "addTrack existing track should fail");
+ } catch (e) {
+ is(e.name, "InvalidAccessError",
+ "addTrack existing track should fail");
+ }
+ });
}
]);
test.run();
});
</script>
</pre>
</body>
</html>
--- a/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
+++ b/dom/media/tests/mochitest/test_peerConnection_replaceVideoThenRenegotiate.html
@@ -31,60 +31,38 @@
]);
addRenegotiation(test.chain,
[
function PC_LOCAL_REPLACE_VIDEO_TRACK_THEN_ADD_SECOND_STREAM(test) {
emitter1.stop();
emitter2.start();
const newstream = emitter2.stream();
const newtrack = newstream.getVideoTracks()[0];
- return test.pcLocal.senderReplaceTrack(0, newtrack, newstream.id)
+ var sender = test.pcLocal._pc.getSenders()[0];
+ return test.pcLocal.senderReplaceTrack(sender, newtrack, newstream)
.then(() => {
test.setMediaConstraints([{video: true}, {video: true}],
[{video: true}]);
- // Use fake:true here since the native fake device on linux
- // doesn't change color as needed by checkVideoPlaying() below.
- return test.pcLocal.getAllUserMedia([{video: true, fake: true}]);
});
},
],
[
- function PC_REMOTE_CHECK_ORIGINAL_TRACK_ENDED(test) {
+ function PC_REMOTE_CHECK_ORIGINAL_TRACK_NOT_ENDED(test) {
+ is(test.pcRemote._pc.getTransceivers().length, 1,
+ "pcRemote should have one transceiver");
+ const track = test.pcRemote._pc.getTransceivers()[0].receiver.track;
+
const vremote = test.pcRemote.remoteMediaElements.find(
- elem => elem.id.includes(emitter1.stream().getTracks()[0].id));
- if (!vremote) {
- return Promise.reject(new Error("Couldn't find video element"));
- }
- ok(vremote.ended, "Original track should have ended after renegotiation");
- },
- function PC_REMOTE_CHECK_REPLACED_TRACK_FLOW(test) {
- const vremote = test.pcRemote.remoteMediaElements.find(
- elem => elem.id.includes(test.pcLocal._pc.getSenders()[0].track.id));
+ elem => elem.id.includes(track.id));
if (!vremote) {
return Promise.reject(new Error("Couldn't find video element"));
}
- return addFinallyToPromise(helper.checkVideoPlaying(vremote))
- .finally(() => emitter2.stop())
- .then(() => {
- const px = helper._helper.getPixel(vremote, 10, 10);
- const isBlue = helper._helper.isPixel(
- px, CaptureStreamTestHelper.prototype.blue, 5);
- const isGrey = helper._helper.isPixel(
- px, CaptureStreamTestHelper.prototype.grey, 5);
- ok(isBlue || isGrey, "replaced track should be blue or grey");
- });
- },
- function PC_REMOTE_CHECK_ADDED_TRACK_FLOW(test) {
- const vremote = test.pcRemote.remoteMediaElements.find(
- elem => elem.id.includes(test.pcLocal._pc.getSenders()[1].track.id));
- if (!vremote) {
- return Promise.reject(new Error("Couldn't find video element"));
- }
+ ok(!vremote.ended, "Original track should not have ended after renegotiation (replaceTrack is not signalled!)");
return helper.checkVideoPlaying(vremote);
- },
+ }
]
);
test.run();
});
});
</script>
--- a/dom/media/tests/mochitest/test_peerConnection_scaleResolution.html
+++ b/dom/media/tests/mochitest/test_peerConnection_scaleResolution.html
@@ -13,73 +13,73 @@
});
const pushPrefs = (...p) => SpecialPowers.pushPrefEnv({set: p});
var mustRejectWith = (msg, reason, f) =>
f().then(() => ok(false, msg),
e => is(e.name, reason, msg));
- function testScale(codec) {
+ async function testScale(codec) {
var pc1 = new RTCPeerConnection();
var pc2 = new RTCPeerConnection();
var add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed);
pc1.onicecandidate = e => add(pc2, e.candidate, generateErrorCallback());
pc2.onicecandidate = e => add(pc1, e.candidate, generateErrorCallback());
info("testing scaling with " + codec);
- pc1.onnegotiationneeded = e =>
- pc1.createOffer()
- .then(d => pc1.setLocalDescription(codec == "VP8"
- ? d
- : (d.sdp = sdputils.removeAllButPayloadType(d.sdp, 126), d)))
- .then(() => pc2.setRemoteDescription(pc1.localDescription))
- .then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
- .then(() => pc1.setRemoteDescription(pc2.localDescription))
- .catch(generateErrorCallback());
+ let stream = await navigator.mediaDevices.getUserMedia({ video: true });
+
+ var v1 = createMediaElement('video', 'v1');
+ var v2 = createMediaElement('video', 'v2');
+
+ var ontrackfired = new Promise(resolve => pc2.ontrack = e => resolve(e));
+ var v2loadedmetadata = new Promise(resolve => v2.onloadedmetadata = resolve);
+
+ is(v2.currentTime, 0, "v2.currentTime is zero at outset");
- return navigator.mediaDevices.getUserMedia({ video: true })
- .then(stream => {
- var v1 = createMediaElement('video', 'v1');
- var v2 = createMediaElement('video', 'v2');
+ v1.srcObject = stream;
+ var sender = pc1.addTrack(stream.getVideoTracks()[0], stream);
- is(v2.currentTime, 0, "v2.currentTime is zero at outset");
+ await mustRejectWith(
+ "Invalid scaleResolutionDownBy must reject", "RangeError",
+ () => sender.setParameters(
+ { encodings:[{ scaleResolutionDownBy: 0.5 } ] })
+ );
- v1.srcObject = stream;
- var sender = pc1.addTrack(stream.getVideoTracks()[0], stream);
+ await sender.setParameters({ encodings: [{ maxBitrate: 60000,
+ scaleResolutionDownBy: 2 }] });
- return mustRejectWith("Invalid scaleResolutionDownBy must reject", "RangeError",
- () => sender.setParameters({ encodings:
- [{ scaleResolutionDownBy: 0.5 } ] }))
- .then(() => sender.setParameters({ encodings: [{ maxBitrate: 60000,
- scaleResolutionDownBy: 2 }] }))
- .then(() => new Promise(resolve => pc2.ontrack = e => resolve(e)))
- .then(e => v2.srcObject = e.streams[0])
- .then(() => new Promise(resolve => v2.onloadedmetadata = resolve))
- .then(() => waitUntil(() => v2.currentTime > 0 && v2.srcObject.currentTime > 0))
- .then(() => ok(v2.currentTime > 0, "v2.currentTime is moving (" + v2.currentTime + ")"))
- .then(() => wait(3000)) // TODO: Bug 1248154
- .then(() => {
- ok(v1.videoWidth > 0, "source width is positive");
- ok(v1.videoHeight > 0, "source height is positive");
- if (v2.videoWidth == 640 && v2.videoHeight == 480) { // TODO: Bug 1248154
- info("Skipping test due to Bug 1248154");
- } else {
- is(v2.videoWidth, v1.videoWidth / 2, "sink is half the width of source");
- is(v2.videoHeight, v1.videoHeight / 2, "sink is half the height of source");
- }
- })
- .then(() => {
- stream.getTracks().forEach(track => track.stop());
- v1.srcObject = v2.srcObject = null;
- })
- })
- .catch(generateErrorCallback());
+ let offer = await pc1.createOffer();
+ if (codec == "VP8") {
+ offer.sdp = sdputils.removeAllButPayloadType(offer.sdp, 126);
+ }
+ await pc1.setLocalDescription(offer);
+ await pc2.setRemoteDescription(pc1.localDescription);
+
+ let answer = await pc2.createAnswer();
+ await pc2.setLocalDescription(answer);
+ await pc1.setRemoteDescription(pc2.localDescription);
+ let trackevent = await ontrackfired;
+
+ v2.srcObject = trackevent.streams[0];
+
+ await v2loadedmetadata;
+
+ await waitUntil(() => v2.currentTime > 0 && v2.srcObject.currentTime > 0);
+ ok(v2.currentTime > 0, "v2.currentTime is moving (" + v2.currentTime + ")");
+
+ ok(v1.videoWidth > 0, "source width is positive");
+ ok(v1.videoHeight > 0, "source height is positive");
+ is(v2.videoWidth, v1.videoWidth / 2, "sink is half the width of source");
+ is(v2.videoHeight, v1.videoHeight / 2, "sink is half the height of source");
+ stream.getTracks().forEach(track => track.stop());
+ v1.srcObject = v2.srcObject = null;
}
pushPrefs(['media.peerconnection.video.lock_scaling', true]).then(() => {
if (!navigator.appVersion.includes("Android")) {
runNetworkTest(() => testScale("VP8").then(() => testScale("H264"))
.then(networkTestFinished));
} else {
// No support for H.264 on Android in automation, see Bug 1355786
--- a/dom/media/tests/mochitest/test_peerConnection_setParameters.html
+++ b/dom/media/tests/mochitest/test_peerConnection_setParameters.html
@@ -12,20 +12,21 @@ createHTML({
visible: true
});
function parameterstest(pc) {
ok(pc.getSenders().length > 0, "have senders");
var sender = pc.getSenders()[0];
var testParameters = (params, errorName, errorMsg) => {
+ info("Trying to set " + JSON.stringify(params));
var validateParameters = (a, b) => {
var validateEncoding = (a, b) => {
- is(a.rid, b.rid || "", "same rid");
+ is(a.rid, b.rid, "same rid");
is(a.maxBitrate, b.maxBitrate, "same maxBitrate");
is(a.scaleResolutionDownBy, b.scaleResolutionDownBy,
"same scaleResolutionDownBy");
};
is(a.encodings.length, (b.encodings || []).length, "same encodings");
a.encodings.forEach((en, i) => validateEncoding(en, b.encodings[i]));
};
--- a/dom/media/tests/mochitest/test_peerConnection_twoAudioTracksInOneStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_twoAudioTracksInOneStream.html
@@ -14,35 +14,23 @@
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.chain.insertAfter("PC_REMOTE_GET_OFFER", [
function PC_REMOTE_OVERRIDE_STREAM_IDS_IN_OFFER(test) {
test._local_offer.sdp = test._local_offer.sdp.replace(
/a=msid:[^\s]*/g,
"a=msid:foo");
- },
- function PC_REMOTE_OVERRIDE_EXPECTED_STREAM_IDS(test) {
- Object.keys(
- test.pcRemote.expectedRemoteTrackInfoById).forEach(trackId => {
- test.pcRemote.expectedRemoteTrackInfoById[trackId].streamId = "foo";
- });
}
]);
test.chain.insertAfter("PC_LOCAL_GET_ANSWER", [
function PC_LOCAL_OVERRIDE_STREAM_IDS_IN_ANSWER(test) {
test._remote_answer.sdp = test._remote_answer.sdp.replace(
/a=msid:[^\s]*/g,
"a=msid:foo");
- },
- function PC_LOCAL_OVERRIDE_EXPECTED_STREAM_IDS(test) {
- Object.keys(
- test.pcLocal.expectedRemoteTrackInfoById).forEach(trackId => {
- test.pcLocal.expectedRemoteTrackInfoById[trackId].streamId = "foo";
- });
}
]);
test.setMediaConstraints([{audio: true}, {audio: true}],
[{audio: true}, {audio: true}]);
test.run();
});
</script>
</pre>
--- a/dom/media/tests/mochitest/test_peerConnection_twoVideoTracksInOneStream.html
+++ b/dom/media/tests/mochitest/test_peerConnection_twoVideoTracksInOneStream.html
@@ -14,35 +14,23 @@
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.chain.insertAfter("PC_REMOTE_GET_OFFER", [
function PC_REMOTE_OVERRIDE_STREAM_IDS_IN_OFFER(test) {
test._local_offer.sdp = test._local_offer.sdp.replace(
/a=msid:[^\s]*/g,
"a=msid:foo");
- },
- function PC_REMOTE_OVERRIDE_EXPECTED_STREAM_IDS(test) {
- Object.keys(
- test.pcRemote.expectedRemoteTrackInfoById).forEach(trackId => {
- test.pcRemote.expectedRemoteTrackInfoById[trackId].streamId = "foo";
- });
}
]);
test.chain.insertAfter("PC_LOCAL_GET_ANSWER", [
function PC_LOCAL_OVERRIDE_STREAM_IDS_IN_ANSWER(test) {
test._remote_answer.sdp = test._remote_answer.sdp.replace(
/a=msid:[^\s]*/g,
"a=msid:foo");
- },
- function PC_LOCAL_OVERRIDE_EXPECTED_STREAM_IDS(test) {
- Object.keys(
- test.pcLocal.expectedRemoteTrackInfoById).forEach(trackId => {
- test.pcLocal.expectedRemoteTrackInfoById[trackId].streamId = "foo";
- });
}
]);
test.setMediaConstraints([{video: true}, {video: true}],
[{video: true}, {video: true}]);
test.run();
});
</script>
</pre>
--- a/dom/media/tests/mochitest/test_peerConnection_verifyAudioAfterRenegotiation.html
+++ b/dom/media/tests/mochitest/test_peerConnection_verifyAudioAfterRenegotiation.html
@@ -43,17 +43,17 @@
}
]);
addRenegotiation(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
test.setMediaConstraints([{audio: true}],
[]);
- return test.pcLocal.getAllUserMedia([{audio: true}]);
+ return test.pcLocal.getAllUserMediaAndAddStreams([{audio: true}]);
},
]
);
test.chain.append([
function CHECK_ASSUMPTIONS2() {
is(test.pcLocal.localMediaElements.length, 2,
"pcLocal should have two media elements");
--- a/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html
+++ b/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html
@@ -73,17 +73,17 @@ runNetworkTest(() => {
addRenegotiation(test.chain,
[
function PC_LOCAL_ADD_SECOND_STREAM(test) {
canvas2 = h2.createAndAppendElement('canvas', 'source_canvas2');
h2.drawColor(canvas2, h2.blue);
stream2 = canvas2.captureStream(0);
- // can't use test.pcLocal.getAllUserMedia([{video: true}]);
+ // can't use test.pcLocal.getAllUserMediaAndAddStreams([{video: true}]);
// because it doesn't let us substitute the capture stream
test.pcLocal.attachLocalStream(stream2);
}
]
);
test.chain.append([
function FIND_REMOTE2_VIDEO() {