614 lines
20 KiB
HTML
614 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<meta charset="utf-8">
|
|
<title>RTCRtpEncodingParameters codec property</title>
|
|
<meta name="timeout" content="long">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="RTCPeerConnection-helper.js"></script>
|
|
<script src="third_party/sdp/sdp.js"></script>
|
|
<script src="simulcast/simulcast.js"></script>
|
|
<script>
|
|
'use strict';
|
|
|
|
function arrayEquals(a, b) {
|
|
return Array.isArray(a) && Array.isArray(b) &&
|
|
a.length === b.length &&
|
|
a.every((val, i) => val === b[i]);
|
|
}
|
|
|
|
async function sleep(timeout) {
|
|
return new Promise(resolve => {
|
|
step_timeout(() => {
|
|
resolve();
|
|
}, timeout);
|
|
});
|
|
}
|
|
|
|
function findFirstCodec(name) {
|
|
return RTCRtpReceiver.getCapabilities(name.split('/')[0]).codecs.filter(c => c.mimeType.localeCompare(name, undefined, { sensitivity: 'base' }) === 0)[0];
|
|
}
|
|
|
|
function codecsNotMatching(mimeType) {
|
|
return RTCRtpReceiver.getCapabilities(mimeType.split('/')[0]).codecs.filter(c => c.mimeType.localeCompare(mimeType, undefined, {sensitivity: 'base'}) !== 0);
|
|
}
|
|
|
|
function assertCodecEquals(a, b) {
|
|
assert_equals(a.mimeType, b.mimeType);
|
|
assert_equals(a.clockRate, b.clockRate);
|
|
assert_equals(a.channels, b.channels);
|
|
assert_equals(a.sdpFmtpLine, b.sdpFmtpLine);
|
|
}
|
|
|
|
async function codecsForSender(sender) {
|
|
const rids = sender.getParameters().encodings.map(e => e.rid);
|
|
const stats = await sender.getStats();
|
|
const codecs = [...stats]
|
|
.filter(([k, v]) => v.type === 'outbound-rtp')
|
|
.sort(([k, v], [k2, v2]) => rids.indexOf(v.rid) - rids.indexOf(v2.rid))
|
|
.map(([k, v]) => stats.get(v.codecId).mimeType);
|
|
return codecs;
|
|
}
|
|
|
|
async function waitForAllLayers(t, sender) {
|
|
const encodings_count = sender.getParameters().encodings.length;
|
|
return step_wait_async(t, async () => {
|
|
const stats = await sender.getStats();
|
|
return [...stats]
|
|
.filter(([k, v]) => v.type === 'outbound-rtp').length == encodings_count;
|
|
}, `Wait for ${encodings_count} layers to start`);
|
|
}
|
|
|
|
function step_wait_async(t, cond, description, timeout=3000, interval=100) {
|
|
return new Promise(resolve => {
|
|
var timeout_full = timeout * t.timeout_multiplier;
|
|
var remaining = Math.ceil(timeout_full / interval);
|
|
|
|
var wait_for_inner = t.step_func(async () => {
|
|
if (await cond()) {
|
|
resolve();
|
|
} else {
|
|
if(remaining === 0) {
|
|
assert(false, "step_wait_async", description,
|
|
"Timed out waiting on condition");
|
|
}
|
|
remaining--;
|
|
await sleep(interval);
|
|
wait_for_inner();
|
|
}
|
|
});
|
|
|
|
wait_for_inner();
|
|
});
|
|
}
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const { sender } = pc.addTransceiver('audio');
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
assert_equals(encoding.codec, undefined);
|
|
}, `Codec should be undefined by default on audio encodings`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const { sender } = pc.addTransceiver('video');
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
assert_equals(encoding.codec, undefined);
|
|
}, `Codec should be undefined by default on video encodings`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const opus = findFirstCodec('audio/opus');
|
|
|
|
const { sender } = pc.addTransceiver('audio', {
|
|
sendEncodings: [{codec: opus}],
|
|
});
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
assertCodecEquals(opus, encoding.codec);
|
|
}, `Creating an audio sender with addTransceiver and codec should work`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
|
|
const { sender } = pc.addTransceiver('video', {
|
|
sendEncodings: [{codec: vp8}],
|
|
});
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
assertCodecEquals(vp8, encoding.codec);
|
|
}, `Creating a video sender with addTransceiver and codec should work`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const opus = findFirstCodec('audio/opus');
|
|
|
|
const { sender } = pc.addTransceiver('audio');
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = opus;
|
|
await sender.setParameters(param);
|
|
param = sender.getParameters();
|
|
encoding = param.encodings[0];
|
|
|
|
assertCodecEquals(opus, encoding.codec);
|
|
|
|
delete encoding.codec;
|
|
await sender.setParameters(param);
|
|
param = sender.getParameters();
|
|
encoding = param.encodings[0];
|
|
|
|
assert_equals(encoding.codec, undefined);
|
|
}, `Setting codec on an audio sender with setParameters should work`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
|
|
const { sender } = pc.addTransceiver('video');
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = vp8;
|
|
await sender.setParameters(param);
|
|
param = sender.getParameters();
|
|
encoding = param.encodings[0];
|
|
|
|
assertCodecEquals(vp8, encoding.codec);
|
|
|
|
delete encoding.codec;
|
|
await sender.setParameters(param);
|
|
param = sender.getParameters();
|
|
encoding = param.encodings[0];
|
|
|
|
assert_equals(encoding.codec, undefined);
|
|
}, `Setting codec on a video sender with setParameters should work`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const newCodec = {
|
|
mimeType: "audio/newCodec",
|
|
clockRate: 90000,
|
|
channel: 2,
|
|
};
|
|
|
|
assert_throws_dom('OperationError', () => pc.addTransceiver('audio', {
|
|
sendEncodings: [{codec: newCodec}],
|
|
}));
|
|
}, `Creating an audio sender with addTransceiver and non-existing codec should throw OperationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const newCodec = {
|
|
mimeType: "dummy/newCodec",
|
|
clockRate: 90000,
|
|
channel: 2,
|
|
};
|
|
|
|
assert_throws_dom('OperationError', () => pc.addTransceiver('audio', {
|
|
sendEncodings: [{codec: newCodec}],
|
|
}));
|
|
}, `Creating an audio sender with addTransceiver and non-existing codec type should throw OperationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const newCodec = {
|
|
mimeType: "video/newCodec",
|
|
clockRate: 90000,
|
|
};
|
|
|
|
assert_throws_dom('OperationError', () => pc.addTransceiver('video', {
|
|
sendEncodings: [{codec: newCodec}],
|
|
}));
|
|
}, `Creating a video sender with addTransceiver and non-existing codec should throw OperationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const newCodec = {
|
|
mimeType: "dummy/newCodec",
|
|
clockRate: 90000,
|
|
};
|
|
|
|
assert_throws_dom('OperationError', () => pc.addTransceiver('video', {
|
|
sendEncodings: [{codec: newCodec}],
|
|
}));
|
|
}, `Creating a video sender with addTransceiver and non-existing codec type should throw OperationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const newCodec = {
|
|
mimeType: "audio/newCodec",
|
|
clockRate: 90000,
|
|
channel: 2,
|
|
};
|
|
|
|
const { sender } = pc.addTransceiver('audio');
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = newCodec;
|
|
await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
|
|
}, `Setting a non-existing codec on an audio sender with setParameters should throw InvalidModificationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc.close());
|
|
|
|
const newCodec = {
|
|
mimeType: "video/newCodec",
|
|
clockRate: 90000,
|
|
};
|
|
|
|
const { sender } = pc.addTransceiver('video');
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = newCodec;
|
|
await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
|
|
}, `Setting a non-existing codec on a video sender with setParameters should throw InvalidModificationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc1 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc2.close());
|
|
|
|
const opus = findFirstCodec('audio/opus');
|
|
const nonOpus = codecsNotMatching(opus.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver('audio');
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = exchangeOfferAnswer(pc1, pc2);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences(nonOpus);
|
|
await negotiated;
|
|
|
|
const sender = transceiver.sender;
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = opus;
|
|
await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
|
|
}, `Setting a non-preferred codec on an audio sender with setParameters should throw InvalidModificationError`);
|
|
|
|
promise_test(async t => {
|
|
const pc1 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc2.close());
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
const nonVP8 = codecsNotMatching(vp8.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver('video');
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = exchangeOfferAnswer(pc1, pc2);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences(nonVP8);
|
|
await negotiated;
|
|
|
|
const sender = transceiver.sender;
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = vp8;
|
|
await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
|
|
}, `Setting a non-preferred codec on a video sender with setParameters should throw InvalidModificationError`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
|
|
const opus = findFirstCodec('audio/opus');
|
|
const nonOpus = codecsNotMatching(opus.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver('audio');
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = exchangeOfferAnswer(pc1, pc2);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences(nonOpus);
|
|
await negotiated;
|
|
|
|
const sender = transceiver.sender;
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = opus;
|
|
await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
|
|
}, `Setting a non-negotiated codec on an audio sender with setParameters should throw InvalidModificationError`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
const nonVP8 = codecsNotMatching(vp8.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver('video');
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = exchangeOfferAnswer(pc1, pc2);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences(nonVP8);
|
|
await negotiated;
|
|
|
|
const sender = transceiver.sender;
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
encoding.codec = vp8;
|
|
await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
|
|
}, `Setting a non-negotiated codec on a video sender with setParameters should throw InvalidModificationError`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
|
|
const opus = findFirstCodec('audio/opus');
|
|
const nonOpus = codecsNotMatching(opus.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver('audio', {
|
|
sendEncodings: [{codec: opus}],
|
|
});
|
|
const sender = transceiver.sender;
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
await exchangeOfferAnswer(pc1, pc2);
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
assertCodecEquals(opus, encoding.codec);
|
|
|
|
pc2.getTransceivers()[0].setCodecPreferences(nonOpus);
|
|
await exchangeOfferAnswer(pc1, pc2);
|
|
|
|
param = sender.getParameters();
|
|
encoding = param.encodings[0];
|
|
|
|
assert_equals(encoding.codec, undefined);
|
|
}, `Codec should be undefined after negotiating away the currently set codec on an audio sender`);
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
const nonVP8 = codecsNotMatching(vp8.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver('video', {
|
|
sendEncodings: [{codec: vp8}],
|
|
});
|
|
const sender = transceiver.sender;
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
await exchangeOfferAnswer(pc1, pc2);
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
|
|
assertCodecEquals(vp8, encoding.codec);
|
|
|
|
pc2.getTransceivers()[0].setCodecPreferences(nonVP8);
|
|
await exchangeOfferAnswer(pc1, pc2);
|
|
|
|
param = sender.getParameters();
|
|
encoding = param.encodings[0];
|
|
|
|
assert_equals(encoding.codec, undefined);
|
|
}, `Codec should be undefined after negotiating away the currently set codec on a video sender`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
const stream = await getNoiseStream({audio:true});
|
|
t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
|
|
|
|
const opus = findFirstCodec('audio/opus');
|
|
const nonOpus = codecsNotMatching(opus.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver(stream.getTracks()[0]);
|
|
const sender = transceiver.sender;
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = exchangeOfferAnswer(pc1, pc2);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences(nonOpus.concat([opus]));
|
|
await negotiated;
|
|
|
|
|
|
let codecs = await codecsForSender(sender);
|
|
assert_not_equals(codecs[0], opus.mimeType);
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
encoding.codec = opus;
|
|
|
|
await sender.setParameters(param);
|
|
|
|
await step_wait_async(t, async () => {
|
|
let old_codecs = codecs;
|
|
codecs = await codecsForSender(sender);
|
|
return !arrayEquals(codecs, old_codecs);
|
|
}, 'Waiting for current codecs to change', 5000, 200);
|
|
|
|
assert_array_equals(codecs, [opus.mimeType]);
|
|
}, `Stats output-rtp should match the selected codec in non-simulcast usecase on an audio sender`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
const stream = await getNoiseStream({video:true});
|
|
t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
const nonVP8 = codecsNotMatching(vp8.mimeType);
|
|
|
|
const transceiver = pc1.addTransceiver(stream.getTracks()[0]);
|
|
const sender = transceiver.sender;
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = exchangeOfferAnswer(pc1, pc2);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences(nonVP8.concat([vp8]));
|
|
await negotiated;
|
|
|
|
let codecs = await codecsForSender(sender);
|
|
assert_not_equals(codecs[0], vp8.mimeType);
|
|
|
|
let param = sender.getParameters();
|
|
let encoding = param.encodings[0];
|
|
encoding.codec = vp8;
|
|
|
|
await sender.setParameters(param);
|
|
|
|
await step_wait_async(t, async () => {
|
|
let old_codecs = codecs;
|
|
codecs = await codecsForSender(sender);
|
|
return !arrayEquals(codecs, old_codecs);
|
|
}, 'Waiting for current codecs to change', 5000, 200);
|
|
|
|
assert_array_equals(codecs, [vp8.mimeType]);
|
|
}, `Stats output-rtp should match the selected codec in non-simulcast usecase on a video sender`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
const stream = await getNoiseStream({video:true});
|
|
t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
const h264 = findFirstCodec('video/H264');
|
|
|
|
const transceiver = pc1.addTransceiver(stream.getTracks()[0], {
|
|
sendEncodings: [{rid: '0'}, {rid: '1'}, {rid: '2'}],
|
|
});
|
|
const sender = transceiver.sender;
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences([h264, vp8]);
|
|
await negotiated;
|
|
|
|
await waitForAllLayers(t, sender);
|
|
|
|
let codecs = await codecsForSender(sender);
|
|
assert_not_equals(codecs[0], vp8.mimeType);
|
|
assert_not_equals(codecs[1], vp8.mimeType);
|
|
assert_not_equals(codecs[2], vp8.mimeType);
|
|
|
|
let param = sender.getParameters();
|
|
param.encodings[0].codec = vp8;
|
|
param.encodings[1].codec = vp8;
|
|
param.encodings[2].codec = vp8;
|
|
|
|
await sender.setParameters(param);
|
|
|
|
// Waiting for 10s as ramp-up time can be slow in the runners.
|
|
await step_wait_async(t, async () => {
|
|
let old_codecs = codecs;
|
|
codecs = await codecsForSender(sender);
|
|
return !arrayEquals(codecs, old_codecs);
|
|
}, 'Waiting for current codecs to change', 10000, 200);
|
|
|
|
assert_array_equals(codecs, [vp8.mimeType, vp8.mimeType, vp8.mimeType]);
|
|
}, `Stats output-rtp should match the selected codec in simulcast usecase on a video sender`);
|
|
|
|
promise_test(async (t) => {
|
|
const pc1 = new RTCPeerConnection();
|
|
const pc2 = new RTCPeerConnection();
|
|
t.add_cleanup(() => pc1.close());
|
|
t.add_cleanup(() => pc2.close());
|
|
const stream = await getNoiseStream({video:true});
|
|
t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
|
|
|
|
const vp8 = findFirstCodec('video/VP8');
|
|
const h264 = findFirstCodec('video/H264');
|
|
|
|
const transceiver = pc1.addTransceiver(stream.getTracks()[0], {
|
|
sendEncodings: [{rid: '0'}, {rid: '1'}, {rid: '2'}],
|
|
});
|
|
const sender = transceiver.sender;
|
|
|
|
exchangeIceCandidates(pc1, pc2);
|
|
const negotiated = doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']);
|
|
const trackEvent = await new Promise(r => pc2.ontrack = r);
|
|
trackEvent.transceiver.setCodecPreferences([h264, vp8]);
|
|
await negotiated;
|
|
|
|
|
|
await waitForAllLayers(t, sender);
|
|
|
|
let codecs = await codecsForSender(sender);
|
|
assert_not_equals(codecs[0], vp8.mimeType);
|
|
assert_not_equals(codecs[1], vp8.mimeType);
|
|
assert_not_equals(codecs[2], vp8.mimeType);
|
|
|
|
let param = sender.getParameters();
|
|
param.encodings[1].codec = vp8;
|
|
|
|
await sender.setParameters(param);
|
|
|
|
await step_wait_async(t, async () => {
|
|
let old_codecs = codecs;
|
|
codecs = await codecsForSender(sender);
|
|
return !arrayEquals(codecs, old_codecs);
|
|
}, 'Waiting for current codecs to change', 5000, 200);
|
|
|
|
assert_not_equals(codecs[0], vp8.mimeType);
|
|
assert_equals(codecs[1], vp8.mimeType);
|
|
assert_not_equals(codecs[2], vp8.mimeType);
|
|
}, `Stats output-rtp should match the selected mixed codecs in simulcast usecase on a video sender`);
|
|
|
|
</script>
|