Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test is not running completely negotiationneeded only trigger using addTrack #433

Closed
andrewvmail opened this issue Nov 3, 2019 · 15 comments
Assignees
Labels
Milestone

Comments

@andrewvmail
Copy link
Contributor

Trying to run the test from the main README.md I had to modify one thing to get pc1 and pc2 to talk to each other.

The negotiationneeded event wont run with

  // Add local stream tracks to RTCPeerConnection
  localStream.getTracks().forEach(function (track) {
     console.log('addTrack', track);
     pc1.addTrack(track);
  });

But runs fine with this line uncommented.

  // Note: Deprecated but supported
  pc1.addStream(localStream);
@hthetiot
Copy link
Contributor

hthetiot commented Nov 3, 2019

@andrewvmail Can you try #407 ?

@hthetiot hthetiot added the bug label Nov 3, 2019
@hthetiot hthetiot changed the title Test not wont run completely Test not wont run completely negotiationneeded only trigger using addStream Nov 5, 2019
@hthetiot hthetiot changed the title Test not wont run completely negotiationneeded only trigger using addStream Test is not running completely negotiationneeded only trigger using addStream Nov 5, 2019
@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

@andrewvmail see #436

@hthetiot hthetiot closed this as completed Nov 5, 2019
@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

@andrewvmail If you run this in the chrome browser console (https://example.com) you will see on Chrome that nor pc2.addtrack or pc2.addStream will trigger if pc1.addTrack does not have a stream seconds argument MediaStream.

Test by yourself on Chrome and Firefox using scripts below.

  1. Without addTrack stream argument.

//
// Container for this sample
//

var appContainer = document.body;
appContainer.innerHTML = "";

//
// Sample getUserMedia
//

// 
var localStream, localVideoEl;
function TestGetUserMedia() {
  localVideoEl = document.createElement('video');
  localVideoEl.style.height = "50vh";
  localVideoEl.setAttribute('autoplay', 'autoplay');
  localVideoEl.setAttribute('playsinline', 'playsinline');
  appContainer.appendChild(localVideoEl);

  return navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
    // Note: Use navigator.mediaDevices.enumerateDevices() Promise to get deviceIds
    /*
    video: {
      // Test Back Camera
      //deviceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      //sourceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      deviceId: {
        exact: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      }
      // Test FrameRate
      frameRate:{ min: 15.0, max: 30.0 } // Note: Back camera may only support max 30 fps
    }, 
    audio: {
      deviceId: {
        exact: 'Built-In Microphone'
      }
    }*/
  }).then(function (stream) {

    console.log('getUserMedia.stream', stream);
    console.log('getUserMedia.stream.getTracks', stream.getTracks());

    // Note: Expose for debug
    localStream = stream;

    // Attach local stream to video element
    localVideoEl.srcObject = localStream;

    return localStream;
   
  }).catch(function (err) {
    console.log('getUserMedia.error', err, err.stack);
  });
}

//
// Sample RTCPeerConnection
// 

var pc1, pc2;

var peerVideoEl, peerStream;
function TestRTCPeerConnection(localStream) {

  pc1 = new RTCPeerConnection();
  pc2 = new RTCPeerConnection();
  
  // Note: Deprecated but supported
  //pc1.addStream(localStream);

  // Add local stream tracks to RTCPeerConnection
  localStream.getTracks().forEach(function (track) {
    console.log('addTrack', track);
    pc1.addTrack(track);
  });

  // Basic RTCPeerConnection Local WebRTC Signaling follow.
  function onAddIceCandidate(pc, can) {
    console.log('addIceCandidate', pc, can);
    return can && pc.addIceCandidate(can).catch(function (err) {
      console.log('addIceCandidateError', err);
    });
  }

  pc1.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc2, e.candidate);
  });
  
  pc2.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc1, e.candidate);
  });

  pc2.addEventListener('addtrack', function (e) {
    console.log('pc2.addtrack', e);
  });

  pc2.addEventListener('addstream', function (e) {
    console.log('pc2.addStream', e);

    // Create peer video element
    peerVideoEl = document.createElement('video');
    peerVideoEl.style.height = "50vh";
    peerVideoEl.setAttribute('autoplay', 'autoplay');
    peerVideoEl.setAttribute('playsinline', 'playsinline');
    appContainer.appendChild(peerVideoEl);

    // Note: Expose for debug
    peerStream = e.stream;

    // Attach peer stream to video element
    peerVideoEl.srcObject = peerStream;
  });

  pc1.addEventListener('iceconnectionstatechange', function (e) {
    console.log('pc1.iceConnectionState', e, pc1.iceConnectionState);

    if (pc1.iceConnectionState === 'completed') {      
      console.log('pc1.getSenders', pc1.getSenders());
      console.log('pc2.getReceivers', pc2.getReceivers());
    }
  });

  pc1.addEventListener('icegatheringstatechange', function (e) {
    console.log('pc1.iceGatheringStateChange', e);
  });

  pc1.addEventListener('negotiationneeded', function (e) {
    console.log('pc1.negotiatioNeeded', e);

    return pc1.createOffer().then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc1.setLocalDescription', desc);
      return pc1.setLocalDescription(desc);
    }).then(function () {
      var desc = {
        type: pc1.localDescription.type,
        sdp: pc1.localDescription.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setRemoteDescription(desc);
    }).then(function () {
      console.log('pc2.createAnswer');
      return pc2.createAnswer();
    }).then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setLocalDescription(d);
    }).then(function () {
      var desc = {
        type: pc2.localDescription.type,
        sdp: pc2.localDescription.sdp
      };
      console.log('pc1.setRemoteDescription', desc);
      return pc1.setRemoteDescription(desc);
    }).catch(function (err) {
      console.log('pc1.createOffer.error', err);
    });
  });
}

function TestRTCPeerConnectionLocal() {
    
  // Note: This allow this sample to run on any Browser
  var cordova = window.cordova;
  if (cordova && cordova.plugins && cordova.plugins.iosrtc) {

    // Expose WebRTC and GetUserMedia SHIM as Globals (Optional)
    // Alternatively WebRTC API will be inside cordova.plugins.iosrtc namespace
    cordova.plugins.iosrtc.registerGlobals();

    // Enable iosrtc debug (Optional)
    cordova.plugins.iosrtc.debug.enable('*', true);
  }

  // Run sample
  TestGetUserMedia().then(function (localStream) {
    TestRTCPeerConnection(localStream); 
  });
}

if (document.readyState === "complete" || document.readyState === "loaded") {
  TestRTCPeerConnectionLocal();
} else {
  window.addEventListener("DOMContentLoaded", TestRTCPeerConnectionLocal);  
}
  1. With addTrack stream argument.

//
// Container for this sample
//

var appContainer = document.body;
appContainer.innerHTML = "";

//
// Sample getUserMedia
//

// 
var localStream, localVideoEl;
function TestGetUserMedia() {
  localVideoEl = document.createElement('video');
  localVideoEl.style.height = "50vh";
  localVideoEl.setAttribute('autoplay', 'autoplay');
  localVideoEl.setAttribute('playsinline', 'playsinline');
  appContainer.appendChild(localVideoEl);

  return navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
    // Note: Use navigator.mediaDevices.enumerateDevices() Promise to get deviceIds
    /*
    video: {
      // Test Back Camera
      //deviceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      //sourceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      deviceId: {
        exact: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      }
      // Test FrameRate
      frameRate:{ min: 15.0, max: 30.0 } // Note: Back camera may only support max 30 fps
    }, 
    audio: {
      deviceId: {
        exact: 'Built-In Microphone'
      }
    }*/
  }).then(function (stream) {

    console.log('getUserMedia.stream', stream);
    console.log('getUserMedia.stream.getTracks', stream.getTracks());

    // Note: Expose for debug
    localStream = stream;

    // Attach local stream to video element
    localVideoEl.srcObject = localStream;

    return localStream;
   
  }).catch(function (err) {
    console.log('getUserMedia.error', err, err.stack);
  });
}

//
// Sample RTCPeerConnection
// 

var pc1, pc2;

var peerVideoEl, peerStream;
function TestRTCPeerConnection(localStream) {

  pc1 = new RTCPeerConnection();
  pc2 = new RTCPeerConnection();
  
  // Note: Deprecated but supported
  //pc1.addStream(localStream);

  // Add local stream tracks to RTCPeerConnection
  var localPeerStream = new MediaStream();
  localStream.getTracks().forEach(function (track) {
    console.log('addTrack', track);
    pc1.addTrack(track, localPeerStream);
  });

  // Basic RTCPeerConnection Local WebRTC Signaling follow.
  function onAddIceCandidate(pc, can) {
    console.log('addIceCandidate', pc, can);
    return can && pc.addIceCandidate(can).catch(function (err) {
      console.log('addIceCandidateError', err);
    });
  }

  pc1.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc2, e.candidate);
  });
  
  pc2.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc1, e.candidate);
  });

  pc2.addEventListener('addtrack', function (e) {
    console.log('pc2.addtrack', e);
  });

  pc2.addEventListener('addstream', function (e) {
    console.log('pc2.addStream', e);

    // Create peer video element
    peerVideoEl = document.createElement('video');
    peerVideoEl.style.height = "50vh";
    peerVideoEl.setAttribute('autoplay', 'autoplay');
    peerVideoEl.setAttribute('playsinline', 'playsinline');
    appContainer.appendChild(peerVideoEl);

    // Note: Expose for debug
    peerStream = e.stream;

    // Attach peer stream to video element
    peerVideoEl.srcObject = peerStream;
  });

  pc1.addEventListener('iceconnectionstatechange', function (e) {
    console.log('pc1.iceConnectionState', e, pc1.iceConnectionState);

    if (pc1.iceConnectionState === 'completed') {      
      console.log('pc1.getSenders', pc1.getSenders());
      console.log('pc2.getReceivers', pc2.getReceivers());
    }
  });

  pc1.addEventListener('icegatheringstatechange', function (e) {
    console.log('pc1.iceGatheringStateChange', e);
  });

  pc1.addEventListener('negotiationneeded', function (e) {
    console.log('pc1.negotiatioNeeded', e);

    return pc1.createOffer().then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc1.setLocalDescription', desc);
      return pc1.setLocalDescription(desc);
    }).then(function () {
      var desc = {
        type: pc1.localDescription.type,
        sdp: pc1.localDescription.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setRemoteDescription(desc);
    }).then(function () {
      console.log('pc2.createAnswer');
      return pc2.createAnswer();
    }).then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setLocalDescription(d);
    }).then(function () {
      var desc = {
        type: pc2.localDescription.type,
        sdp: pc2.localDescription.sdp
      };
      console.log('pc1.setRemoteDescription', desc);
      return pc1.setRemoteDescription(desc);
    }).catch(function (err) {
      console.log('pc1.createOffer.error', err);
    });
  });
}

function TestRTCPeerConnectionLocal() {
    
  // Note: This allow this sample to run on any Browser
  var cordova = window.cordova;
  if (cordova && cordova.plugins && cordova.plugins.iosrtc) {

    // Expose WebRTC and GetUserMedia SHIM as Globals (Optional)
    // Alternatively WebRTC API will be inside cordova.plugins.iosrtc namespace
    cordova.plugins.iosrtc.registerGlobals();

    // Enable iosrtc debug (Optional)
    cordova.plugins.iosrtc.debug.enable('*', true);
  }

  // Run sample
  TestGetUserMedia().then(function (localStream) {
    TestRTCPeerConnection(localStream); 
  });
}

if (document.readyState === "complete" || document.readyState === "loaded") {
  TestRTCPeerConnectionLocal();
} else {
  window.addEventListener("DOMContentLoaded", TestRTCPeerConnectionLocal);  
}

@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

Fun fact without webrtc-adatper Chrome will not trigger pc2.addTrack anyway.

@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

I will revert #436 partially cause we should not addTrack MediaStream by default.
But I have updated the README sample instead with addTrack MediaStream argument.

@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

Related #437

@hthetiot hthetiot changed the title Test is not running completely negotiationneeded only trigger using addStream Test is not running completely negotiationneeded only trigger using addTrack Nov 5, 2019
@hthetiot hthetiot self-assigned this Nov 5, 2019
@hthetiot hthetiot added this to the 6.0.x milestone Nov 5, 2019
@hthetiot hthetiot reopened this Nov 5, 2019
@hthetiot hthetiot closed this as completed Nov 5, 2019
@hthetiot hthetiot modified the milestones: 6.0.x, 6.0.2 Nov 5, 2019
@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

6.0.2 contains partial fix:

@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

@andrewvmail can you test 6.0.2 and confirm, thank you.

@hthetiot
Copy link
Contributor

hthetiot commented Nov 5, 2019

#437 will make it match browser implementation

@andrewvmail
Copy link
Contributor Author

@hthetiot thanks for looking into this, didnt mean to get you on a wild goose chase. I dont actually use the negotiationeeded api in my app like that. It's only when I use the README.md code snippet just to test the plugin.

I was assuming the snippet was meant to be a copy and paste and it just works. To make testing easier?

What I do is

cordova create hello com.example.hello HelloWorld
cd hello
cordova plugin add cordova-plugin-iosrtc
cordova platform add ios
cordova build ios
open platforms/ios/HelloWorld.xcworkspace 
# run simulator 
# attach a safari web debugger and paste the code in readme and expects to run?
# pc1 and pc2 is in console so i can play around with it like test dtmf

Right now above doesn't work without commenting out that addStream

@andrewvmail
Copy link
Contributor Author

Oh actually confirming now README.md snippets copy pasted fine. But I think thats with the recent change that will be reverted.

@hthetiot
Copy link
Contributor

hthetiot commented Nov 6, 2019

@andrewvmail You actually helped find a bug, where no stream with addTrack would have prevented the track to not being added. Thx

@hthetiot
Copy link
Contributor

hthetiot commented Nov 6, 2019

Only the default MediaStream on addRrack will be reverted in favor of #436

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants