webrtc-video.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree.
  7. */
  8. 'use strict';
  9. var startButton = document.getElementById('startButton');
  10. var callButton = document.getElementById('callButton');
  11. var hangupButton = document.getElementById('hangupButton');
  12. callButton.disabled = true;
  13. hangupButton.disabled = true;
  14. startButton.onclick = start;
  15. callButton.onclick = call;
  16. hangupButton.onclick = hangup;
  17. var startTime;
  18. var localVideo = document.getElementById('localVideo');
  19. var remoteVideo = document.getElementById('remoteVideo');
  20. localVideo.addEventListener('loadedmetadata', function() {
  21. trace('Local video videoWidth: ' + this.videoWidth +
  22. 'px, videoHeight: ' + this.videoHeight + 'px');
  23. });
  24. remoteVideo.addEventListener('loadedmetadata', function() {
  25. trace('Remote video videoWidth: ' + this.videoWidth +
  26. 'px, videoHeight: ' + this.videoHeight + 'px');
  27. });
  28. remoteVideo.onresize = function() {
  29. trace('Remote video size changed to ' +
  30. remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
  31. // We'll use the first onsize callback as an indication that video has started
  32. // playing out.
  33. if (startTime) {
  34. var elapsedTime = window.performance.now() - startTime;
  35. trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
  36. startTime = null;
  37. }
  38. };
  39. var localStream;
  40. var pc1;
  41. var pc2;
  42. var offerOptions = {
  43. offerToReceiveAudio: 1,
  44. offerToReceiveVideo: 1
  45. };
  46. function getName(pc) {
  47. return (pc === pc1) ? 'pc1' : 'pc2';
  48. }
  49. function getOtherPc(pc) {
  50. return (pc === pc1) ? pc2 : pc1;
  51. }
  52. function gotStream(stream) {
  53. trace('Received local stream');
  54. localVideo.srcObject = stream;
  55. localStream = stream;
  56. callButton.disabled = false;
  57. }
  58. function start() {
  59. trace('Requesting local stream');
  60. startButton.disabled = true;
  61. navigator.mediaDevices.getUserMedia({
  62. audio: true,
  63. video: true
  64. })
  65. .then(gotStream)
  66. .catch(function(e) {
  67. alert('getUserMedia() error: ' + e.name);
  68. });
  69. }
  70. function call() {
  71. callButton.disabled = true;
  72. hangupButton.disabled = false;
  73. trace('Starting call');
  74. startTime = window.performance.now();
  75. var videoTracks = localStream.getVideoTracks();
  76. var audioTracks = localStream.getAudioTracks();
  77. if (videoTracks.length > 0) {
  78. trace('Using video device: ' + videoTracks[0].label);
  79. }
  80. if (audioTracks.length > 0) {
  81. trace('Using audio device: ' + audioTracks[0].label);
  82. }
  83. var servers = null;
  84. pc1 = new RTCPeerConnection(servers);
  85. trace('Created local peer connection object pc1');
  86. pc1.onicecandidate = function(e) {
  87. onIceCandidate(pc1, e);
  88. };
  89. pc2 = new RTCPeerConnection(servers);
  90. trace('Created remote peer connection object pc2');
  91. pc2.onicecandidate = function(e) {
  92. onIceCandidate(pc2, e);
  93. };
  94. pc1.oniceconnectionstatechange = function(e) {
  95. onIceStateChange(pc1, e);
  96. };
  97. pc2.oniceconnectionstatechange = function(e) {
  98. onIceStateChange(pc2, e);
  99. };
  100. pc2.onaddstream = gotRemoteStream;
  101. pc1.addStream(localStream);
  102. trace('Added local stream to pc1');
  103. trace('pc1 createOffer start');
  104. pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError,
  105. offerOptions);
  106. }
  107. function onCreateSessionDescriptionError(error) {
  108. trace('Failed to create session description: ' + error.toString());
  109. }
  110. function onCreateOfferSuccess(desc) {
  111. trace('Offer from pc1\n' + desc.sdp);
  112. trace('pc1 setLocalDescription start');
  113. pc1.setLocalDescription(desc, function() {
  114. onSetLocalSuccess(pc1);
  115. }, onSetSessionDescriptionError);
  116. trace('pc2 setRemoteDescription start');
  117. pc2.setRemoteDescription(desc, function() {
  118. onSetRemoteSuccess(pc2);
  119. }, onSetSessionDescriptionError);
  120. trace('pc2 createAnswer start');
  121. // Since the 'remote' side has no media stream we need
  122. // to pass in the right constraints in order for it to
  123. // accept the incoming offer of audio and video.
  124. pc2.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
  125. }
  126. function onSetLocalSuccess(pc) {
  127. trace(getName(pc) + ' setLocalDescription complete');
  128. }
  129. function onSetRemoteSuccess(pc) {
  130. trace(getName(pc) + ' setRemoteDescription complete');
  131. }
  132. function onSetSessionDescriptionError(error) {
  133. trace('Failed to set session description: ' + error.toString());
  134. }
  135. function gotRemoteStream(e) {
  136. remoteVideo.srcObject = e.stream;
  137. trace('pc2 received remote stream');
  138. }
  139. function onCreateAnswerSuccess(desc) {
  140. trace('Answer from pc2:\n' + desc.sdp);
  141. trace('pc2 setLocalDescription start');
  142. pc2.setLocalDescription(desc, function() {
  143. onSetLocalSuccess(pc2);
  144. }, onSetSessionDescriptionError);
  145. trace('pc1 setRemoteDescription start');
  146. pc1.setRemoteDescription(desc, function() {
  147. onSetRemoteSuccess(pc1);
  148. }, onSetSessionDescriptionError);
  149. }
  150. function onIceCandidate(pc, event) {
  151. if (event.candidate) {
  152. getOtherPc(pc).addIceCandidate(new RTCIceCandidate(event.candidate),
  153. function() {
  154. onAddIceCandidateSuccess(pc);
  155. },
  156. function(err) {
  157. onAddIceCandidateError(pc, err);
  158. }
  159. );
  160. trace(getName(pc) + ' ICE candidate: \n' + event.candidate.candidate);
  161. }
  162. }
  163. function onAddIceCandidateSuccess(pc) {
  164. trace(getName(pc) + ' addIceCandidate success');
  165. }
  166. function onAddIceCandidateError(pc, error) {
  167. trace(getName(pc) + ' failed to add ICE Candidate: ' + error.toString());
  168. }
  169. function onIceStateChange(pc, event) {
  170. if (pc) {
  171. trace(getName(pc) + ' ICE state: ' + pc.iceConnectionState);
  172. console.log('ICE state change event: ', event);
  173. }
  174. }
  175. function hangup() {
  176. trace('Ending call');
  177. pc1.close();
  178. pc2.close();
  179. pc1 = null;
  180. pc2 = null;
  181. hangupButton.disabled = true;
  182. callButton.disabled = false;
  183. }