Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 <html> | |
| 2 <head> | |
| 3 <script type="text/javascript"> | |
| 4 $ = function(id) { | |
| 5 return document.getElementById(id); | |
| 6 }; | |
| 7 | |
| 8 var gFirstConnection = null; | |
| 9 var gSecondConnection = null; | |
| 10 | |
| 11 function call(constraints) { | |
|
perkj_chrome
2012/12/04 10:51:43
Can we instead use the example in http://dev.w3.or
phoglund_chromium
2012/12/04 13:03:27
In that case we would need to run two tabs and imp
| |
| 12 navigator.webkitGetUserMedia(constraints, okCallback, failedCallback); | |
| 13 } | |
| 14 | |
| 15 function failedCallback(error) { | |
| 16 document.title = 'getUserMedia request failed with code ' + error.code; | |
| 17 } | |
| 18 | |
| 19 function okCallback(localStream) { | |
| 20 var localStreamUrl = webkitURL.createObjectURL(localStream); | |
| 21 $('local-view').src = localStreamUrl; | |
| 22 | |
| 23 callUsingStream(localStream); | |
| 24 } | |
| 25 | |
| 26 function callUsingStream(localStream) { | |
| 27 gFirstConnection = new webkitRTCPeerConnection(null, null); | |
| 28 gFirstConnection.onicecandidate = onIceCandidateToFirst; | |
| 29 gFirstConnection.addStream(localStream); | |
| 30 gFirstConnection.createOffer(onOfferCreated); | |
| 31 } | |
| 32 | |
| 33 function onOfferCreated(offer) { | |
| 34 gFirstConnection.setLocalDescription(offer); | |
| 35 | |
| 36 receiveCall(offer.sdp); | |
| 37 } | |
| 38 | |
| 39 function receiveCall(offerSdp) { | |
| 40 gSecondConnection = new webkitRTCPeerConnection(null, null); | |
| 41 gSecondConnection.onicecandidate = onIceCandidateToSecond; | |
| 42 gSecondConnection.onaddstream = onRemoteStream; | |
| 43 | |
| 44 var parsedOffer = new RTCSessionDescription({ type: 'offer', | |
| 45 sdp: offerSdp }); | |
| 46 gSecondConnection.setRemoteDescription(parsedOffer); | |
| 47 | |
| 48 gSecondConnection.createAnswer(onAnswerCreated); | |
| 49 } | |
| 50 | |
| 51 function onAnswerCreated(answer) { | |
| 52 gSecondConnection.setLocalDescription(answer); | |
| 53 handleAnswer(answer.sdp); | |
| 54 } | |
| 55 | |
| 56 function handleAnswer(answerSdp) { | |
| 57 var parsedAnswer = new RTCSessionDescription({ type: 'answer', | |
| 58 sdp: answerSdp }); | |
| 59 gFirstConnection.setRemoteDescription(parsedAnswer); | |
| 60 } | |
| 61 | |
| 62 function onIceCandidateToFirst(event) { | |
| 63 if (event.candidate) { | |
| 64 var candidate = new RTCIceCandidate(event.candidate); | |
| 65 gSecondConnection.addIceCandidate(candidate); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 function onIceCandidateToSecond(event) { | |
| 70 if (event.candidate) { | |
| 71 var candidate = new RTCIceCandidate(event.candidate); | |
| 72 gFirstConnection.addIceCandidate(candidate); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 function onRemoteStream(e) { | |
| 77 var remoteStreamUrl = webkitURL.createObjectURL(e.stream); | |
| 78 var remoteVideo = $('remote-view'); | |
| 79 remoteVideo.src = remoteStreamUrl; | |
| 80 | |
| 81 waitForVideo(remoteVideo, 320, 240); | |
| 82 } | |
| 83 | |
| 84 function waitForVideo(videoElement, width, height) { | |
| 85 document.title = 'Waiting for video...'; | |
| 86 var canvas = $('canvas'); | |
| 87 setInterval(function() { | |
| 88 var context = canvas.getContext('2d'); | |
| 89 context.drawImage(videoElement, 0, 0, 320, 240); | |
| 90 var pixels = context.getImageData(0, 0, 320, 240).data; | |
| 91 | |
| 92 if (isVideoPlaying(pixels, width, height)) | |
| 93 testSuccessful(); | |
| 94 }, 100); | |
| 95 } | |
| 96 | |
| 97 // This very basic video verification algorithm will be satisfied if any | |
| 98 // pixels are nonzero in a small sample area in the middle. It relies on the | |
| 99 // assumption that a video element with null source just presents zeroes. | |
| 100 function isVideoPlaying(pixels, width, height) { | |
|
perkj_chrome
2012/12/04 10:51:43
Why not use your existing video checker?
phoglund_chromium
2012/12/04 13:03:27
Good point. I thought about it, but then I would h
| |
| 101 // Sample somewhere near the middle of the image. | |
| 102 var middle = width * height / 2; | |
| 103 for (var i = 0; i < 20; i++) { | |
| 104 if (pixels[middle + i] > 0) { | |
| 105 return true; | |
| 106 } | |
| 107 } | |
| 108 return false; | |
| 109 } | |
| 110 | |
| 111 function testSuccessful() { | |
| 112 document.title = 'OK'; | |
| 113 } | |
| 114 </script> | |
| 115 </head> | |
| 116 <body> | |
| 117 <table border="0"> | |
| 118 <tr> | |
| 119 <td>Local Preview</td> | |
| 120 <td>Remote Stream</td> | |
| 121 <td>Capturing Canvas</td> | |
| 122 </tr> | |
| 123 <tr> | |
| 124 <td><video width="320" height="240" id="local-view" | |
| 125 autoplay="autoplay"></video></td> | |
| 126 <td><video width="320" height="240" id="remote-view" | |
| 127 autoplay="autoplay"></video></td> | |
| 128 <td><canvas width="320" height="240" id="canvas"></canvas></td> | |
| 129 </tr> | |
| 130 <tr> | |
| 131 <td colspan="3">You should see the same animated feed in all three | |
| 132 displays (the canvas will lag a bit). | |
| 133 </td> | |
| 134 </table> | |
| 135 </body> | |
| 136 </html> | |
| OLD | NEW |