Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
"use strict";
createHTML({
title: "MediaStreamTrack.clone()",
bug: "1208371"
});
var testSingleTrackClonePlayback = constraints =>
getUserMedia(constraints).then(stream => {
info("Test clone()ing an " + constraints + " gUM track");
var track = stream.getTracks()[0];
var clone = track.clone();
checkMediaStreamTrackCloneAgainstOriginal(clone, track);
info("Stopping original track");
track.stop();
info("Creating new stream for clone");
var cloneStream = new MediaStream([clone]);
checkMediaStreamContains(cloneStream, [clone]);
info("Testing playback of track clone");
var test = createMediaElement('video', 'testClonePlayback');
var playback = new MediaStreamPlayback(test, cloneStream);
return playback.playMedia(false);
});
runTest(() => Promise.resolve()
.then(() => testSingleTrackClonePlayback({audio: true}))
.then(() => testSingleTrackClonePlayback({video: true}))
.then(() => getUserMedia({video: true})).then(stream => {
info("Test cloning a track into inception");
var track = stream.getTracks()[0];
var clone = track;
var clones = Array(10).fill().map(() => clone = clone.clone());
var inceptionClone = clones.pop();
checkMediaStreamTrackCloneAgainstOriginal(inceptionClone, track);
var cloneStream = new MediaStream();
cloneStream.addTrack(inceptionClone);
// cloneStream is now essentially the same as stream.clone();
checkMediaStreamCloneAgainstOriginal(cloneStream, stream);
var test = createMediaElement('video', 'testClonePlayback');
var playback = new MediaStreamPlayback(test, cloneStream);
return playback.playMedia(false).then(() => {
info("Testing that clones of ended tracks are ended");
cloneStream.clone().getTracks().forEach(t =>
is(t.readyState, "ended", "Track " + t.id + " should be ended"));
})
.then(() => {
clones.forEach(t => t.stop());
track.stop();
});
})
.then(() => getUserMedia({audio: true, video: true})).then(stream => {
info("Test adding many track clones to the original stream");
const LOOPS = 3;
for (var i = 0; i < LOOPS; i++) {
stream.getTracks().forEach(t => stream.addTrack(t.clone()));
}
is(stream.getVideoTracks().length, Math.pow(2, LOOPS),
"The original track should contain the original video track and all the video clones");
stream.getTracks().forEach(t1 => is(stream.getTracks()
.filter(t2 => t1.id == t2.id)
.length,
1, "Each track should be unique"));
var test = createMediaElement('video', 'testClonePlayback');
var playback = new MediaStreamPlayback(test, stream);
return playback.playMedia(false);
})
.then(() => {
info("Testing audio content routing with MediaStreamTrack.clone()");
var ac = new AudioContext();
var osc1kOriginal = createOscillatorStream(ac, 1000);
var audioTrack1kOriginal = osc1kOriginal.getTracks()[0];
var audioTrack1kClone = audioTrack1kOriginal.clone();
var osc5kOriginal = createOscillatorStream(ac, 5000);
var audioTrack5kOriginal = osc5kOriginal.getTracks()[0];
var audioTrack5kClone = audioTrack5kOriginal.clone();
return Promise.resolve().then(() => {
info("Analysing audio output enabled and disabled tracks that don't affect each other");
audioTrack1kOriginal.enabled = true;
audioTrack5kOriginal.enabled = false;
audioTrack1kClone.enabled = false;
audioTrack5kClone.enabled = true;
var analyser =
new AudioStreamAnalyser(ac, new MediaStream([audioTrack1kOriginal,
audioTrack5kOriginal]));
return analyser.waitForAnalysisSuccess(array =>
array[analyser.binIndexForFrequency(50)] < 50 &&
array[analyser.binIndexForFrequency(1000)] > 200 &&
array[analyser.binIndexForFrequency(3000)] < 50 &&
array[analyser.binIndexForFrequency(5000)] < 50)
.then(() => analyser.disconnect())
.then(() => {
var cloneAnalyser =
new AudioStreamAnalyser(ac, new MediaStream([audioTrack1kClone,
audioTrack5kClone]));
return cloneAnalyser.waitForAnalysisSuccess(array =>
array[cloneAnalyser.binIndexForFrequency(1000)] < 50 &&
array[cloneAnalyser.binIndexForFrequency(3000)] < 50 &&
array[cloneAnalyser.binIndexForFrequency(5000)] > 200 &&
array[cloneAnalyser.binIndexForFrequency(10000)] < 50)
.then(() => cloneAnalyser.disconnect());
})
// Restore original tracks
.then(() => [audioTrack1kOriginal,
audioTrack5kOriginal,
audioTrack1kClone,
audioTrack5kClone].forEach(t => t.enabled = true));
}).then(() => {
info("Analysing audio output of 1k original and 5k clone.");
var stream = new MediaStream();
stream.addTrack(audioTrack1kOriginal);
stream.addTrack(audioTrack5kClone);
var analyser = new AudioStreamAnalyser(ac, stream);
return analyser.waitForAnalysisSuccess(array =>
array[analyser.binIndexForFrequency(50)] < 50 &&
array[analyser.binIndexForFrequency(1000)] > 200 &&
array[analyser.binIndexForFrequency(3000)] < 50 &&
array[analyser.binIndexForFrequency(5000)] > 200 &&
array[analyser.binIndexForFrequency(10000)] < 50)
.then(() => {
info("Waiting for tracks to stop");
stream.getTracks().forEach(t => t.stop());
return analyser.waitForAnalysisSuccess(array =>
array[analyser.binIndexForFrequency(50)] < 50 &&
array[analyser.binIndexForFrequency(1000)] < 50 &&
array[analyser.binIndexForFrequency(3000)] < 50 &&
array[analyser.binIndexForFrequency(5000)] < 50 &&
array[analyser.binIndexForFrequency(10000)] < 50);
}).then(() => analyser.disconnect());
}).then(() => {
info("Analysing audio output of clones of clones (1kx2 + 5kx4)");
var stream = new MediaStream([audioTrack1kClone.clone(),
audioTrack5kOriginal.clone().clone().clone().clone()]);
var analyser = new AudioStreamAnalyser(ac, stream);
return analyser.waitForAnalysisSuccess(array =>
array[analyser.binIndexForFrequency(50)] < 50 &&
array[analyser.binIndexForFrequency(1000)] > 200 &&
array[analyser.binIndexForFrequency(3000)] < 50 &&
array[analyser.binIndexForFrequency(5000)] > 200 &&
array[analyser.binIndexForFrequency(10000)] < 50)
.then(() => analyser.disconnect());
});
}));
</script>
</pre>
</body>
</html>