Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(694)

Side by Side Diff: content/test/data/media/peerconnection-call.html

Issue 11785041: Add content browser tests for PeerConnection DataChannels. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moved to content/browser/media and added OWNERS files. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/test/data/media/OWNERS ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <html> 1 <html>
2 <head> 2 <head>
3 <script type="text/javascript"> 3 <script type="text/javascript">
4 $ = function(id) { 4 $ = function(id) {
5 return document.getElementById(id); 5 return document.getElementById(id);
6 }; 6 };
7 7
8 var gFirstConnection = null; 8 var gFirstConnection = null;
9 var gSecondConnection = null; 9 var gSecondConnection = null;
10 var gTestWithoutMsidAndBundle = false; 10 var gTestWithoutMsidAndBundle = false;
11 11
12 // Number of test events to occur before the test pass. When the test pass,
13 // the document title change to OK.
14 var gNumberOfExpectedEvents = 0;
15
16 // Number of events that currently have occured.
17 var gNumberOfEvents = 0;
18
19 // Test that we can setup call with an audio and video track.
12 function call(constraints) { 20 function call(constraints) {
21 createConnections(null);
13 navigator.webkitGetUserMedia(constraints, okCallback, failedCallback); 22 navigator.webkitGetUserMedia(constraints, okCallback, failedCallback);
23 waitForVideo($('remote-view'), 320, 240);
14 } 24 }
15 25
26 // Test that we can setup call with an audio and video track and
27 // simulate that the remote peer don't support MSID.
16 function callWithoutMsidAndBundle() { 28 function callWithoutMsidAndBundle() {
29 createConnections(null);
17 gTestWithoutMsidAndBundle = true; 30 gTestWithoutMsidAndBundle = true;
18 navigator.webkitGetUserMedia({audio:true, video:true}, okCallback, 31 navigator.webkitGetUserMedia({audio:true, video:true}, okCallback,
19 failedCallback); 32 failedCallback);
33 waitForVideo($('remote-view'), 320, 240);
34 }
35
36 // Test only a data channel.
37 function callWithDataOnly() {
38 createConnections({optional:[{RtpDataChannels: true}]});
39 setupDataChannel();
40 gFirstConnection.createOffer(onOfferCreated);
41 }
42
43 // Test call with audio, video and a data channel.
44 function callWithDataAndMedia() {
45 createConnections({optional:[{RtpDataChannels: true}]});
46 setupDataChannel();
47 navigator.webkitGetUserMedia({audio:true, video:true}, okCallback,
48 failedCallback);
49 waitForVideo($('remote-view'), 320, 240);
50 }
51
52 // Test call with a data channel and later add audio and video.
53 function callWithDataAndLaterAddMedia() {
54 // TODO(perkj): This is needed for now until
55 // https://code.google.com/p/webrtc/issues/detail?id=1203 is fixed.
56 gTestWithoutMsidAndBundle = true;
57
58 createConnections({optional:[{RtpDataChannels: true}]});
59 setupDataChannel();
60 gFirstConnection.createOffer(onOfferCreated);
61
62 navigator.webkitGetUserMedia({audio:true, video:true}, okCallback,
63 failedCallback);
64 waitForVideo($('remote-view'), 320, 240);
65 }
66
67 // This function is used for setting up a test that:
68 // 1. Creates a data channel on |gFirstConnection| and sends data to
69 // |gSecondConnection|.
70 // 2. When data is received on |gSecondConnection| a message
71 // is sent to |gFirstConnection|.
72 // 3. When data is received on |gFirstConnection|, the data
73 // channel is closed. The test passes when the state transition completes.
74 function setupDataChannel() {
75 var sendDataString = "send some text on a data channel."
76 firstDataChannel = gFirstConnection.createDataChannel(
77 "sendDataChannel", {reliable : false});
78 expectEquals('connecting', firstDataChannel.readyState);
79
80 // When |firstDataChannel| transition to open state, send a text string.
81 firstDataChannel.onopen = function() {
82 expectEquals('open', firstDataChannel.readyState);
83 firstDataChannel.send(sendDataString);
84 }
85
86 // When |firstDataChannel| receive a message, close the channel and
87 // initiate a new offer/answer exchange to complete the closure.
88 firstDataChannel.onmessage = function(event) {
89 expectEquals(event.data, sendDataString);
90 firstDataChannel.close();
91 gFirstConnection.createOffer(onOfferCreated);
92 }
93
94 // When |firstDataChannel| transition to closed state, the test pass.
95 addExpectedEvent();
96 firstDataChannel.onclose = function() {
97 expectEquals('closed', firstDataChannel.readyState);
98 eventOccured();
99 }
100
101 // Event handler for when |gSecondConnection| receive a new dataChannel.
102 gSecondConnection.ondatachannel = function (event) {
103 var secondDataChannel = event.channel;
104
105 // When |secondDataChannel| receive a message, send a message back.
106 secondDataChannel.onmessage = function(event) {
107 expectEquals(event.data, sendDataString);
108 // TODO(perkj): Currently we sometimes can't send a message here since
109 // the the |dataChannel.readyState| has not transitioned to open yet.
110 // http://code.google.com/p/webrtc/issues/detail?id=1262
111 if (secondDataChannel.readyState == "open") {
112 secondDataChannel.send(sendDataString);
113 } else {
114 secondDataChannel.onopen = function(event) {
115 expectEquals('open', secondDataChannel.readyState);
116 secondDataChannel.send(sendDataString);
117 }
118 }
119 }
120 }
20 } 121 }
21 122
22 function failedCallback(error) { 123 function failedCallback(error) {
23 document.title = 'getUserMedia request failed with code ' + error.code; 124 document.title = 'getUserMedia request failed with code ' + error.code;
24 } 125 }
25 126
26 function okCallback(localStream) { 127 function okCallback(localStream) {
27 var localStreamUrl = webkitURL.createObjectURL(localStream); 128 var localStreamUrl = webkitURL.createObjectURL(localStream);
28 $('local-view').src = localStreamUrl; 129 $('local-view').src = localStreamUrl;
29 130
30 callUsingStream(localStream); 131 callUsingStream(localStream);
31 } 132 }
32 133
33 function callUsingStream(localStream) { 134 function createConnections(constraints) {
34 gFirstConnection = new webkitRTCPeerConnection(null, null); 135 gFirstConnection = new webkitRTCPeerConnection(null, constraints);
35 gFirstConnection.onicecandidate = onIceCandidateToFirst; 136 gFirstConnection.onicecandidate = onIceCandidateToFirst;
137
138 gSecondConnection = new webkitRTCPeerConnection(null, constraints);
139 gSecondConnection.onicecandidate = onIceCandidateToSecond;
140 gSecondConnection.onaddstream = onRemoteStream;
141 }
142
143 function callUsingStream(localStream) {
36 gFirstConnection.addStream(localStream); 144 gFirstConnection.addStream(localStream);
37 gFirstConnection.createOffer(onOfferCreated); 145 gFirstConnection.createOffer(onOfferCreated);
38 } 146 }
39 147
40 function onOfferCreated(offer) { 148 function onOfferCreated(offer) {
41 gFirstConnection.setLocalDescription(offer); 149 gFirstConnection.setLocalDescription(offer);
42 150 receiveOffer(offer.sdp);
43 receiveCall(offer.sdp);
44 } 151 }
45 152
46 function receiveCall(offerSdp) { 153 function receiveOffer(offerSdp) {
47 if (gTestWithoutMsidAndBundle) { 154 if (gTestWithoutMsidAndBundle) {
48 offerSdp = removeMsidAndBundle(offerSdp); 155 offerSdp = removeMsidAndBundle(offerSdp);
49 } 156 }
50 gSecondConnection = new webkitRTCPeerConnection(null, null);
51 gSecondConnection.onicecandidate = onIceCandidateToSecond;
52 gSecondConnection.onaddstream = onRemoteStream;
53 157
54 var parsedOffer = new RTCSessionDescription({ type: 'offer', 158 var parsedOffer = new RTCSessionDescription({ type: 'offer',
55 sdp: offerSdp }); 159 sdp: offerSdp });
56 gSecondConnection.setRemoteDescription(parsedOffer); 160 gSecondConnection.setRemoteDescription(parsedOffer);
57
58 gSecondConnection.createAnswer(onAnswerCreated); 161 gSecondConnection.createAnswer(onAnswerCreated);
59 } 162 }
60 163
61 function removeMsidAndBundle(offerSdp) { 164 function removeMsidAndBundle(offerSdp) {
62 offerSdp = offerSdp.replace(/a=msid-semantics.*\r\n/g, ''); 165 offerSdp = offerSdp.replace(/a=msid-semantics.*\r\n/g, '');
63 offerSdp = offerSdp.replace('a=group:BUNDLE audio video\r\n', ''); 166 offerSdp = offerSdp.replace('a=group:BUNDLE audio video\r\n', '');
64 offerSdp = offerSdp.replace('a=mid:audio\r\n', ''); 167 offerSdp = offerSdp.replace('a=mid:audio\r\n', '');
65 offerSdp = offerSdp.replace('a=mid:video\r\n', ''); 168 offerSdp = offerSdp.replace('a=mid:video\r\n', '');
66 offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, ''); 169 offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, '');
67 return offerSdp; 170 return offerSdp;
(...skipping 18 matching lines...) Expand all
86 } 189 }
87 190
88 function onIceCandidateToSecond(event) { 191 function onIceCandidateToSecond(event) {
89 if (event.candidate) { 192 if (event.candidate) {
90 var candidate = new RTCIceCandidate(event.candidate); 193 var candidate = new RTCIceCandidate(event.candidate);
91 gFirstConnection.addIceCandidate(candidate); 194 gFirstConnection.addIceCandidate(candidate);
92 } 195 }
93 } 196 }
94 197
95 function onRemoteStream(e) { 198 function onRemoteStream(e) {
96 var remoteStreamUrl = webkitURL.createObjectURL(e.stream);
97 var remoteVideo = $('remote-view');
98 remoteVideo.src = remoteStreamUrl;
99
100 if (gTestWithoutMsidAndBundle && e.stream.label != "default") { 199 if (gTestWithoutMsidAndBundle && e.stream.label != "default") {
101 document.title = 'a default remote stream was expected but instead ' + 200 document.title = 'a default remote stream was expected but instead ' +
102 e.stream.label + ' was received.'; 201 e.stream.label + ' was received.';
103 return; 202 return;
104 } 203 }
105 204 var remoteStreamUrl = webkitURL.createObjectURL(e.stream);
106 waitForVideo(remoteVideo, 320, 240); 205 var remoteVideo = $('remote-view');
206 remoteVideo.src = remoteStreamUrl;
107 } 207 }
108 208
109 // TODO(phoglund): perhaps use the video detector in chrome/test/data/webrtc/? 209 // TODO(phoglund): perhaps use the video detector in chrome/test/data/webrtc/?
110 function waitForVideo(videoElement, width, height) { 210 function waitForVideo(videoElement, width, height) {
111 document.title = 'Waiting for video...'; 211 document.title = 'Waiting for video...';
212 addExpectedEvent();
112 var canvas = $('canvas'); 213 var canvas = $('canvas');
113 setInterval(function() { 214 setInterval(function() {
114 var context = canvas.getContext('2d'); 215 var context = canvas.getContext('2d');
115 context.drawImage(videoElement, 0, 0, width, height); 216 context.drawImage(videoElement, 0, 0, width, height);
116 var pixels = context.getImageData(0, 0, width, height).data; 217 var pixels = context.getImageData(0, 0, width, height).data;
117 218
118 if (isVideoPlaying(pixels, width, height)) 219 if (isVideoPlaying(pixels, width, height))
119 testSuccessful(); 220 eventOccured();
120 }, 100); 221 }, 100);
121 } 222 }
122 223
123 // This very basic video verification algorithm will be satisfied if any 224 // This very basic video verification algorithm will be satisfied if any
124 // pixels are nonzero in a small sample area in the middle. It relies on the 225 // pixels are nonzero in a small sample area in the middle. It relies on the
125 // assumption that a video element with null source just presents zeroes. 226 // assumption that a video element with null source just presents zeroes.
126 function isVideoPlaying(pixels, width, height) { 227 function isVideoPlaying(pixels, width, height) {
127 // Sample somewhere near the middle of the image. 228 // Sample somewhere near the middle of the image.
128 var middle = width * height / 2; 229 var middle = width * height / 2;
129 for (var i = 0; i < 20; i++) { 230 for (var i = 0; i < 20; i++) {
130 if (pixels[middle + i] > 0) { 231 if (pixels[middle + i] > 0) {
131 return true; 232 return true;
132 } 233 }
133 } 234 }
134 return false; 235 return false;
135 } 236 }
237
238
239 // This function matches |left| and |right| and throws an exception if the
240 // values don't match.
241 function expectEquals(left, right) {
242 if (left != right) {
243 var s = "expectEquals failed left: " + left + " right: " + right;
244 document.title = s;
245 throw s;
246 }
247 }
136 248
137 function testSuccessful() { 249 function addExpectedEvent() {
138 document.title = 'OK'; 250 ++gNumberOfExpectedEvents;
251 }
252
253 function eventOccured() {
254 ++gNumberOfEvents;
255 if (gNumberOfEvents == gNumberOfExpectedEvents) {
256 document.title = 'OK';
257 }
139 } 258 }
140 </script> 259 </script>
141 </head> 260 </head>
142 <body> 261 <body>
143 <table border="0"> 262 <table border="0">
144 <tr> 263 <tr>
145 <td>Local Preview</td> 264 <td>Local Preview</td>
146 <td>Remote Stream</td> 265 <td>Remote Stream</td>
147 <td>Capturing Canvas</td> 266 <td>Capturing Canvas</td>
148 </tr> 267 </tr>
149 <tr> 268 <tr>
150 <td><video width="320" height="240" id="local-view" 269 <td><video width="320" height="240" id="local-view"
151 autoplay="autoplay"></video></td> 270 autoplay="autoplay"></video></td>
152 <td><video width="320" height="240" id="remote-view" 271 <td><video width="320" height="240" id="remote-view"
153 autoplay="autoplay"></video></td> 272 autoplay="autoplay"></video></td>
154 <td><canvas width="320" height="240" id="canvas"></canvas></td> 273 <td><canvas width="320" height="240" id="canvas"></canvas></td>
155 </tr> 274 </tr>
156 <tr> 275 <tr>
157 <td colspan="3">You should see the same animated feed in all three 276 <td colspan="3">You should see the same animated feed in all three
158 displays (the canvas will lag a bit). 277 displays (the canvas will lag a bit).
159 </td> 278 </td>
160 </table> 279 </table>
161 </body> 280 </body>
162 </html> 281 </html>
OLDNEW
« no previous file with comments | « content/test/data/media/OWNERS ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698