Search code examples
video-streamingwebrtcsdp

WebRTC Order of processing after onnegotiateneeded on getlocalmedia success


Have a webrtc environment up and running without any problem when i get usermedia before starting sessions (e.g., at initialize time). However, when i get the usermedia on session initiation and answer, i am not successful at adding the answer side media to the session (i.e., the initiating side video is visible at the answer side but the answer side video is not visible at the initiating side). I have spent many hours trying to handle this without success and was hoping that someone could clarify a points on the processing of the onnegotiationneeded event.

Situation is as follows:

Side A initiates session, gets user media and once the usermedia is available and added to the peer connection, an SDP offer is generated and sent to the remote side.

Side B receives the offer, causes a ringing type event on screen and requests usermedia once the user decides to answer. The success call for the getusermedia adds a localdescription to the peer connection and at some point an onnegotiationeeded event is generated.

All seems to happen well (e.g., on side B - offer and candidates via the signaling channel, then have_remote_offer, remote stream added , etc..),

However, i am unclear whether the answering side should generate an SDP answer or an SDP offer after the renegotiation (i.e., when processing the onnegotiationneeded event).

Also, is it best to wait until the getusermedia returns a success before sending an SDP answer back, or should the SDP answer be sent based on the initiating side SDP offer, without waiting for the local usermedia and then sending another SDP (e.g., either offer or answer per the prior paragraph) after the onnegotiationneeded?

On a somewhat related question is the PRAnswer actually used - i have not seen such in the message traces.


Solution

  • On receiving an offer, side B needs to produce an answer, not an offer.

    Side B should not be renegotiating during an answer, because it is already in the middle of a negotiation. In other words, you don't want negotiationneeded firing during an answer.

    You say negotiationneeded is firing on side B. That is bad.

    There may be three reasons it is firing, and without code I cannot tell which one:

    1. You're adding the stream before calling setRemoteDescription with the offer.
    2. The number of video and/or audio tracks in your stream exceeds what's allowed in the offer.
    3. You are using Chrome.

    According to the spec, negotiationneeded only fires when the signalingState is "stable" (i.e. not negotiating), but not if localDescription at that time matches what you've added and is allowed by the offer.

    So ensure you're doing three things:

    1. Call setRemoteDescription(offer) before adding the getUserMedia stream.
    2. Unless both peers are adding the same number of video and/or audio tracks, use RTCOfferOptions with createOffer.
    3. In Chrome, be prepared to ignore negotiationneeded anyway, since it appears to have a bug where it fires outside of "stable" state, which will happen in this case.

    Here's an example that works in Firefox and Chrome 45.

    In Firefox you'll see:

    addStream in have-remote-offer
    checking
    connected
    

    whereas in Chrome 45 you'll see:

    addStream in have-remote-offer
    onnegotiationneeded fired in have-remote-offer
    checking
    connected
    

    because of the bug.

    Negotiation will still complete even if your answer has fewer tracks, so if you want to answer quickly, that is one way to go (but then you'll need to re-negotiate later when you add media).

    PRAnswer is not implemented in any browser AFAIK.