-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathchrome_freeze_issue.html
105 lines (87 loc) · 3.25 KB
/
chrome_freeze_issue.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
Chrome <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1052353">Issue 1052353</a>: video freezes when switching tracks between local and remote video
<h2> <h2>
<button id="demo">Start Demo</button>
<br>
<video id="local_video" width="200" autoplay=true></video>
<br>
<video id="remote_video" width="200" autoplay=true></video>
<br>
<video id="target_video" width="400" autoplay=true></video>
<br>
<script>
function log(message) {
console.log(message);
const p = document.createElement('p');
p.innerText = message;;
document.body.appendChild(p);
}
document.getElementById('demo').onclick = main;
const target_video = document.getElementById('target_video');
const remote_video = document.getElementById('remote_video');
const local_video = document.getElementById('local_video');
// returns a video stream of white noise.
async function getWhiteNoiseStream() {
let ctx = canvas.getContext('2d');
ctx.fillRect(0, 0, canvas.width, canvas.height);
let p = ctx.getImageData(0, 0, canvas.width, canvas.height);
requestAnimationFrame(function draw(){
for (var i = 0; i < p.data.length; i++) {
p.data[i++] = p.data[i++] = p.data[i++] = Math.random() * 255;
}
ctx.putImageData(p, 0, 0);
requestAnimationFrame(draw);
});
return canvas.captureStream(60);
};
// sets the video into target
function switchVideo(srcElement) {
const srcMediaStream = srcElement.srcObject;
if (target_video.srcObject == null) {
target_video.srcObject = new MediaStream();
}
const targetMediaStream = target_video.srcObject;
targetMediaStream.getVideoTracks().forEach(track => targetMediaStream.removeTrack(track));
srcMediaStream.getVideoTracks().forEach(track => targetMediaStream.addTrack(track));
}
async function waitASecond() {
return new Promise(resolve => setTimeout(resolve, 1000));
}
async function main() {
log('Step 1: get GUM stream');
const userMediaStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });
local_video.srcObject = userMediaStream;
log('Step 2: Negotiate and Get Remote Stream');
remote_video.srcObject = await negotiate(userMediaStream);;
await waitASecond();
log('Step 3: Set Remote Stream in target_video');
switchVideo(remote_video);
await waitASecond();
log('Step 4: Set Local Stream in target_video');
switchVideo(local_video);
await waitASecond();
log('Step 5: Set Remote Stream in target_video');
switchVideo(remote_video);
log('Notice that target video element is frozen!');
}
//
// 1) creates peer connections
// 2) adds local stream
// 3) negotiates connection
// 4) returns remote stream.
async function negotiate(localStream) {
const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
pc2.onicecandidate = (event) => event.candidate && pc1.addIceCandidate(event.candidate);
pc1.onicecandidate = (event) => event.candidate && pc2.addIceCandidate(event.candidate);
return new Promise( async (resolve) => {
pc1.addStream(localStream);
pc2.onaddstream = (event) => resolve(event.stream);
const offer = await pc1.createOffer();
pc1.setLocalDescription(offer);
pc2.setRemoteDescription(offer);
const answer = await pc2.createAnswer();
pc2.setLocalDescription(answer);
pc1.setRemoteDescription(answer);
});
}
</script>