<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>RTCRtpScriptTransformer.sendKeyFrameRequest tests</title>
<meta name='timeout' content='long'>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src='../mediacapture-streams/permission-helper.js'></script>
</head>
<body>
<video id='video1' autoplay></video>
<video id='video2' autoplay></video>
<script src ='routines.js'></script>
<script>
const sendKeyFrameRequest = (port, opts) => postMethod(port, 'sendKeyFrameRequest', opts);
const waitForFrame = port => postMethod(port, 'waitForFrame');
promise_test(async (test) => {
const {sender, receiver} = await createConnectionWithTransform(test, 'script-transform-sendKeyFrameRequest.js', {video: true});
assert_equals(await waitForFrame(receiver.transform.port), 'got frame');
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'success');
assert_equals(await sendKeyFrameRequest(sender.transform.port), 'failure: InvalidStateError');
video1.srcObject = new MediaStream([receiver.track]);
await video1.play();
}, 'sendKeyFrameRequest resolves for video receiver, and throws for video sender');
promise_test(async (test) => {
const {sender, receiver} = await createConnectionWithTransform(test, 'script-transform-sendKeyFrameRequest.js', {audio: true});
assert_equals(await waitForFrame(receiver.transform.port), 'got frame');
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'failure: InvalidStateError');
assert_equals(await waitForFrame(sender.transform.port), 'got frame');
assert_equals(await sendKeyFrameRequest(sender.transform.port), 'failure: InvalidStateError');
video1.srcObject = new MediaStream([receiver.track]);
await video1.play();
}, 'sendKeyFrameRequest throws for audio sender/receiver');
promise_test(async (test) => {
const [senderTransform] = await createTransforms('script-transform-sendKeyFrameRequest.js');
assert_equals(await sendKeyFrameRequest(senderTransform.port), 'failure: InvalidStateError');
}, 'sendKeyFrameRequest throws for unused transforms');
promise_test(async (test) => {
const {sender, receiver} = await createConnectionWithTransform(test, 'script-transform-sendKeyFrameRequest.js', {video: true});
assert_equals(await waitForFrame(receiver.transform.port), 'got frame');
const receiverTransform = receiver.transform;
assert_equals(await sendKeyFrameRequest(receiverTransform.port), 'success');
// TODO: Spec currently says that this will immediately cause the transformer
// to stop working. This may change.
receiver.transform = null;
assert_equals(await sendKeyFrameRequest(receiverTransform.port), 'failure: InvalidStateError');
}, 'sendKeyFrameRequest throws for unset transforms');
promise_test(async (test) => {
const {sender, receiver, senderPc, receiverPc} = await createConnectionWithTransform(test, 'script-transform-sendKeyFrameRequest.js', {video: true});
assert_equals(await waitForFrame(receiver.transform.port), 'got frame');
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'success');
senderPc.getTransceivers()[0].direction = 'inactive';
await senderPc.setLocalDescription();
await receiverPc.setRemoteDescription(senderPc.localDescription);
await receiverPc.setLocalDescription();
await senderPc.setRemoteDescription(receiverPc.localDescription);
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'failure: InvalidStateError');
senderPc.getTransceivers()[0].direction = 'sendonly';
await senderPc.setLocalDescription();
await receiverPc.setRemoteDescription(senderPc.localDescription);
await receiverPc.setLocalDescription();
await senderPc.setRemoteDescription(receiverPc.localDescription);
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'success');
}, 'sendKeyFrameRequest rejects when the receiver is negotiated inactive, and resumes succeeding when negotiated back to active');
promise_test(async (test) => {
const {sender, receiver, senderPc, receiverPc} = await createConnectionWithTransform(test, 'script-transform-sendKeyFrameRequest.js', {video: true});
assert_equals(await waitForFrame(receiver.transform.port), 'got frame');
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'success');
receiverPc.getTransceivers()[0].stop();
assert_equals(await sendKeyFrameRequest(receiver.transform.port), 'failure: InvalidStateError');
}, 'sendKeyFrameRequest rejects when the receiver is stopped');
// Testing that sendKeyFrameRequest actually results in the sending of keyframe
// requests is effectively impossible, because there is no API to expose the
// reception of a keyframe request, keyframes are sent regularly anyway, and
// the spec allows the receiver to ignore these calls if sending a keyframe
// request is 'not deemed appropriate'! sendKeyFrameRequest is at most a
// suggestion.
</script>
</body>
</html>