зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1663368 - Add mochitests for simulcast with custom layer-resolution-order. r=dminor
Differential Revision: https://phabricator.services.mozilla.com/D90667
This commit is contained in:
Родитель
4af1240826
Коммит
fd6604f554
|
@ -217,8 +217,12 @@ skip-if = (os == "win" && processor == "aarch64") # aarch64 due to 1538440
|
|||
[test_peerConnection_scaleResolution.html]
|
||||
[test_peerConnection_simulcastOffer.html]
|
||||
skip-if = toolkit == 'android' # no simulcast support on android
|
||||
[test_peerConnection_simulcastOffer_lowResFirst.html]
|
||||
skip-if = toolkit == 'android' # no simulcast support on android
|
||||
[test_peerConnection_simulcastAnswer.html]
|
||||
skip-if = toolkit == 'android' # no simulcast support on android
|
||||
[test_peerConnection_simulcastAnswer_lowResFirst.html]
|
||||
skip-if = toolkit == 'android' # no simulcast support on android
|
||||
[test_peerConnection_simulcastOddResolution.html]
|
||||
skip-if = toolkit == 'android' # no simulcast support on android
|
||||
[test_peerConnection_relayOnly.html]
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
<!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: "1231507",
|
||||
title: "Basic video-only peer connection with Simulcast answer, first rid has lowest resolution",
|
||||
visible: true
|
||||
});
|
||||
|
||||
function addRIDExtension(pc, extensionId) {
|
||||
const receivers = pc._pc.getReceivers();
|
||||
is(receivers.length, 1, "We have exactly one RTP receiver");
|
||||
const receiver = receivers[0];
|
||||
|
||||
SpecialPowers.wrap(receiver).mozAddRIDExtension(extensionId);
|
||||
}
|
||||
|
||||
function selectRecvRID(pc, rid) {
|
||||
const receivers = pc._pc.getReceivers();
|
||||
is(receivers.length, 1, "We have exactly one RTP receiver");
|
||||
const receiver = receivers[0];
|
||||
|
||||
SpecialPowers.wrap(receiver).mozAddRIDFilter(rid);
|
||||
}
|
||||
|
||||
runNetworkTest(() =>
|
||||
pushPrefs(['media.peerconnection.simulcast', true],
|
||||
// 180Kbps was determined empirically, set well-higher than
|
||||
// the 80Kbps+overhead needed for the two simulcast streams.
|
||||
// 100Kbps was apparently too low.
|
||||
['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => {
|
||||
let emitter, helper;
|
||||
|
||||
test = new PeerConnectionTest({bundle: false});
|
||||
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||
|
||||
test.chain.replace("PC_REMOTE_GUM", [
|
||||
function PC_REMOTE_CANVAS_CAPTURESTREAM(test) {
|
||||
emitter = new VideoFrameEmitter();
|
||||
helper = new VideoStreamHelper();
|
||||
test.pcRemote.attachLocalStream(emitter.stream());
|
||||
emitter.start();
|
||||
}
|
||||
]);
|
||||
|
||||
test.chain.insertAfter('PC_REMOTE_GET_OFFER', [
|
||||
function PC_REMOTE_SET_RIDS(test) {
|
||||
const senders = test.pcRemote._pc.getSenders();
|
||||
is(senders.length, 1, "We have exactly one RTP sender");
|
||||
const sender = senders[0];
|
||||
ok(sender.track, "Sender has a track");
|
||||
|
||||
return sender.setParameters({
|
||||
encodings: [{ rid: "foo", maxBitrate: 40000, scaleResolutionDownBy: 2 },
|
||||
{ rid: "bar", maxBitrate: 40000 }]
|
||||
});
|
||||
},
|
||||
function PC_LOCAL_ADD_RIDS_TO_OFFER(test) {
|
||||
// Create a dummy offer, and use it to set simulcast stuff on the
|
||||
// offer we will actually be using.
|
||||
return test.createOffer(test.pcRemote).then(offer => {
|
||||
test._local_offer.sdp = sdputils.transferSimulcastProperties(
|
||||
offer.sdp, test._local_offer.sdp);
|
||||
info("Offer with RIDs: " + JSON.stringify(test._local_offer));
|
||||
ok(test._local_offer.sdp.match(/a=simulcast:/), "Modified offer has simulcast");
|
||||
ok(test._local_offer.sdp.match(/a=rid:foo/), "Modified offer has rid foo");
|
||||
ok(test._local_offer.sdp.match(/a=rid:bar/), "Modified offer has rid bar");
|
||||
ok(test._local_offer.sdp.match(/urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/), "Modified offer has RID");
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
||||
test.chain.insertAfter('PC_LOCAL_GET_ANSWER',[
|
||||
function PC_LOCAL_REMOVE_SIMULCAST_ATTRS_FROM_ANSWER(test) {
|
||||
test._remote_answer.sdp =
|
||||
sdputils.removeSimulcastProperties(test._remote_answer.sdp);
|
||||
}
|
||||
]);
|
||||
|
||||
// do this after set remote description so the MediaPipeline
|
||||
// has been created.
|
||||
test.chain.insertAfter('PC_LOCAL_SET_REMOTE_DESCRIPTION',[
|
||||
function PC_LOCAL_SET_RTP_FIRST_RID(test) {
|
||||
const extmap_id = test._local_offer.sdp.match(
|
||||
"a=extmap:([0-9+])/recvonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
|
||||
ok(extmap_id, "Local offer has extmap id for simulcast: " + extmap_id[1]);
|
||||
// Cause pcLocal to filter out everything but RID "bar", only
|
||||
// allowing one of the simulcast streams through.
|
||||
addRIDExtension(test.pcLocal, extmap_id[1]);
|
||||
selectRecvRID(test.pcLocal, "bar");
|
||||
}
|
||||
]);
|
||||
|
||||
test.chain.append([
|
||||
async function PC_LOCAL_WAIT_FOR_FRAMES() {
|
||||
const vremote = test.pcLocal.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcLocal");
|
||||
emitter.start();
|
||||
await helper.checkVideoPlaying(vremote);
|
||||
emitter.stop();
|
||||
},
|
||||
function PC_LOCAL_CHECK_SIZE_1() {
|
||||
const vlocal = test.pcRemote.localMediaElements[0];
|
||||
const vremote = test.pcLocal.remoteMediaElements[0];
|
||||
ok(vlocal, "Should have local video element for pcRemote");
|
||||
ok(vremote, "Should have remote video element for pcLocal");
|
||||
is(vlocal.videoWidth, 50, "correct source width");
|
||||
is(vlocal.videoHeight, 50, "correct source height");
|
||||
is(vremote.videoWidth, 48,
|
||||
"sink is same width as source, modulo our cropping algorithm");
|
||||
is(vremote.videoHeight, 48,
|
||||
"sink is same height as source, modulo our cropping algorithm");
|
||||
},
|
||||
function PC_LOCAL_SET_RTP_SECOND_RID(test) {
|
||||
// Now, cause pcLocal to filter out everything but RID "foo", only
|
||||
// allowing the other simulcast stream through.
|
||||
selectRecvRID(test.pcLocal, "foo");
|
||||
},
|
||||
function PC_LOCAL_WAIT_FOR_SECOND_MEDIA_FLOW(test) {
|
||||
return test.pcLocal.waitForMediaFlow();
|
||||
},
|
||||
async function PC_LOCAL_WAIT_FOR_FRAMES_2() {
|
||||
const vremote = test.pcLocal.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcLocal");
|
||||
emitter.start();
|
||||
await helper.checkVideoPlaying(vremote);
|
||||
emitter.stop();
|
||||
},
|
||||
// For some reason, even though we're getting a 24x24 stream, sometimes
|
||||
// the resolution isn't updated on the video element on the first frame.
|
||||
async function PC_LOCAL_WAIT_FOR_FRAMES_3() {
|
||||
const vremote = test.pcLocal.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcLocal");
|
||||
emitter.start();
|
||||
await helper.checkVideoPlaying(vremote);
|
||||
emitter.stop();
|
||||
},
|
||||
function PC_LOCAL_CHECK_SIZE_2() {
|
||||
const vlocal = test.pcRemote.localMediaElements[0];
|
||||
const vremote = test.pcLocal.remoteMediaElements[0];
|
||||
ok(vlocal, "Should have local video element for pcRemote");
|
||||
ok(vremote, "Should have remote video element for pcLocal");
|
||||
is(vlocal.videoWidth, 50, "correct source width");
|
||||
is(vlocal.videoHeight, 50, "correct source height");
|
||||
is(vremote.videoWidth, 24,
|
||||
"sink is 1/2 width of source, modulo our cropping algorithm");
|
||||
is(vremote.videoHeight, 24,
|
||||
"sink is 1/2 height of source, modulo our cropping algorithm");
|
||||
},
|
||||
]);
|
||||
|
||||
return test.run();
|
||||
})
|
||||
.catch(e => ok(false, "unexpected failure: " + e)));
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -185,6 +185,20 @@
|
|||
await setParameters(test, emitter, encodings);
|
||||
await checkResolutions(test, emitter);
|
||||
},
|
||||
async function PC_LOCAL_CHANGE_PARAMS_3() {
|
||||
encodings.find(({rid}) => rid == "foo").scaleResolutionDownBy = 6;
|
||||
encodings.find(({rid}) => rid == "bar").scaleResolutionDownBy = 5;
|
||||
encodings.find(({rid}) => rid == "baz").scaleResolutionDownBy = 4;
|
||||
await setParameters(test, emitter, encodings);
|
||||
await checkResolutions(test, emitter);
|
||||
},
|
||||
async function PC_LOCAL_CHANGE_PARAMS_4() {
|
||||
encodings.find(({rid}) => rid == "foo").scaleResolutionDownBy = 4;
|
||||
encodings.find(({rid}) => rid == "bar").scaleResolutionDownBy = 1;
|
||||
encodings.find(({rid}) => rid == "baz").scaleResolutionDownBy = 2;
|
||||
await setParameters(test, emitter, encodings);
|
||||
await checkResolutions(test, emitter);
|
||||
},
|
||||
]);
|
||||
|
||||
await test.run();
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
<script type="application/javascript" src="parser_rtp.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: "1231507",
|
||||
title: "Basic video-only peer connection with Simulcast offer, first rid has lowest resolution",
|
||||
visible: true
|
||||
});
|
||||
|
||||
function addRIDExtension(pc, extensionId) {
|
||||
const receivers = pc._pc.getReceivers();
|
||||
is(receivers.length, 1, "We have exactly one RTP receiver");
|
||||
const receiver = receivers[0];
|
||||
|
||||
SpecialPowers.wrap(receiver).mozAddRIDExtension(extensionId);
|
||||
}
|
||||
|
||||
function selectRecvRID(pc, rid) {
|
||||
const receivers = pc._pc.getReceivers();
|
||||
is(receivers.length, 1, "We have exactly one RTP receiver");
|
||||
const receiver = receivers[0];
|
||||
|
||||
SpecialPowers.wrap(receiver).mozAddRIDFilter(rid);
|
||||
}
|
||||
|
||||
runNetworkTest(() =>
|
||||
pushPrefs(['media.peerconnection.simulcast', true],
|
||||
// 180Kbps was determined empirically, set well-higher than
|
||||
// the 80Kbps+overhead needed for the two simulcast streams.
|
||||
// 100Kbps was apparently too low.
|
||||
['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => {
|
||||
let emitter, helper;
|
||||
|
||||
const test = new PeerConnectionTest({bundle: false});
|
||||
test.setMediaConstraints([{video: true}], []);
|
||||
|
||||
test.chain.replace("PC_LOCAL_GUM", [
|
||||
function PC_LOCAL_CANVAS_CAPTURESTREAM(test) {
|
||||
emitter = new VideoFrameEmitter();
|
||||
helper = new VideoStreamHelper();
|
||||
test.pcLocal.attachLocalStream(emitter.stream());
|
||||
emitter.start();
|
||||
}
|
||||
]);
|
||||
|
||||
test.chain.insertBefore('PC_LOCAL_CREATE_OFFER', [
|
||||
function PC_LOCAL_SET_RIDS(test) {
|
||||
const senders = test.pcLocal._pc.getSenders();
|
||||
is(senders.length, 1, "We have exactly one RTP sender");
|
||||
const sender = senders[0];
|
||||
ok(sender.track, "Sender has a track");
|
||||
|
||||
return sender.setParameters({
|
||||
encodings: [{ rid: "foo", maxBitrate: 40000, scaleResolutionDownBy: 2 },
|
||||
{ rid: "bar", maxBitrate: 40000 }]
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
||||
test.chain.insertAfter('PC_LOCAL_GET_ANSWER', [
|
||||
function PC_LOCAL_ADD_RIDS_TO_ANSWER(test) {
|
||||
test._remote_answer.sdp = sdputils.transferSimulcastProperties(
|
||||
test.originalOffer.sdp, test._remote_answer.sdp);
|
||||
info("Answer with RIDs: " + JSON.stringify(test._remote_answer));
|
||||
ok(test._remote_answer.sdp.match(/a=simulcast:/), "Modified answer has simulcast");
|
||||
ok(test._remote_answer.sdp.match(/a=rid:foo/), "Modified answer has rid foo");
|
||||
ok(test._remote_answer.sdp.match(/a=rid:bar/), "Modified answer has rid bar");
|
||||
ok(test._remote_answer.sdp.match(/urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/), "Modified answer has RID");
|
||||
}
|
||||
]);
|
||||
|
||||
// For storing the rid extension so it can be checked in the RTP
|
||||
let ridExtensionId = 0;
|
||||
|
||||
// do this after set local description so the MediaPipeline
|
||||
// has been created.
|
||||
test.chain.insertAfter('PC_REMOTE_SET_LOCAL_DESCRIPTION',[
|
||||
function PC_REMOTE_SET_RTP_FIRST_RID(test) {
|
||||
const extmap_id = test.originalOffer.sdp.match(
|
||||
"a=extmap:([0-9+])/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
|
||||
ok(extmap_id, "Original offer has extmap id for simulcast: " + extmap_id[1]);
|
||||
ridExtensionId = extmap_id[1];
|
||||
// Cause pcRemote to filter out everything but RID "foo", only
|
||||
// allowing one of the simulcast streams through.
|
||||
addRIDExtension(test.pcRemote, extmap_id[1]);
|
||||
selectRecvRID(test.pcRemote, "foo");
|
||||
}
|
||||
]);
|
||||
|
||||
let getRtpPacket = (pc) => {
|
||||
pc.mozEnablePacketDump(0, "rtp", false);
|
||||
return new Promise((res, rej) =>
|
||||
pc.mozSetPacketCallback((...args) => {
|
||||
res([...args]);
|
||||
pc.mozSetPacketCallback(() => {});
|
||||
pc.mozDisablePacketDump(0, "rtp", false);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
test.chain.insertBefore('PC_REMOTE_WAIT_FOR_MEDIA_FLOW', [
|
||||
async function PC_REMOTE_CHECK_RID_IN_RTP() {
|
||||
let pc = SpecialPowers.wrap(test.pcRemote._pc);
|
||||
let [level, type, sending, data] = await getRtpPacket(pc);
|
||||
let extensions = ParseRtpPacket(data).header.extensions;
|
||||
ok(ridExtensionId, "RID extension ID has been extracted from SDP");
|
||||
let ridExt = extensions.find(e => e.id == ridExtensionId);
|
||||
ok(ridExt, "RID is present in RTP.");
|
||||
is(new TextDecoder('utf-8').decode(ridExt.data), "foo",
|
||||
"RID is 'foo'.");
|
||||
}
|
||||
]);
|
||||
|
||||
test.chain.append([
|
||||
async function PC_REMOTE_WAIT_FOR_FRAMES() {
|
||||
const vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
emitter.start();
|
||||
await helper.checkVideoPlaying(vremote);
|
||||
emitter.stop();
|
||||
},
|
||||
function PC_REMOTE_CHECK_SIZE_1() {
|
||||
const vlocal = test.pcLocal.localMediaElements[0];
|
||||
const vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vlocal, "Should have local video element for pcLocal");
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
is(vlocal.videoWidth, 50, "correct source width");
|
||||
is(vlocal.videoHeight, 50, "correct source height");
|
||||
is(vremote.videoWidth, 24,
|
||||
"sink is 1/2 width of source, modulo our cropping algorithm");
|
||||
is(vremote.videoHeight, 24,
|
||||
"sink is 1/2 height of source, modulo our cropping algorithm");
|
||||
},
|
||||
function PC_REMOTE_SET_RTP_SECOND_RID(test) {
|
||||
// Now, cause pcRemote to filter out everything but RID "bar", only
|
||||
// allowing the other simulcast stream through.
|
||||
selectRecvRID(test.pcRemote, "bar");
|
||||
},
|
||||
function PC_REMOTE_WAIT_FOR_SECOND_MEDIA_FLOW(test) {
|
||||
return test.pcRemote.waitForMediaFlow();
|
||||
},
|
||||
async function PC_REMOTE_WAIT_FOR_FRAMES_2() {
|
||||
const vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
emitter.start();
|
||||
await helper.checkVideoPlaying(vremote);
|
||||
emitter.stop();
|
||||
},
|
||||
// For some reason, even though we're getting a 25x25 stream, sometimes
|
||||
// the resolution isn't updated on the video element on the first frame.
|
||||
async function PC_REMOTE_WAIT_FOR_FRAMES_3() {
|
||||
const vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
emitter.start();
|
||||
await helper.checkVideoPlaying(vremote);
|
||||
emitter.stop();
|
||||
},
|
||||
function PC_REMOTE_CHECK_SIZE_2() {
|
||||
const vlocal = test.pcLocal.localMediaElements[0];
|
||||
const vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vlocal, "Should have local video element for pcLocal");
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
is(vlocal.videoWidth, 50, "correct source width");
|
||||
is(vlocal.videoHeight, 50, "correct source height");
|
||||
is(vremote.videoWidth, 48,
|
||||
"sink is same width as source, modulo our cropping algorithm");
|
||||
is(vremote.videoHeight, 48,
|
||||
"sink is same height as source, modulo our cropping algorithm");
|
||||
},
|
||||
]);
|
||||
|
||||
return test.run();
|
||||
})
|
||||
.catch(e => ok(false, "unexpected failure: " + e)));
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче