Skip to content
Sean DuBois edited this page Nov 18, 2020 · 13 revisions

Breaking Changes

Trickle ICE is now enabled by default

Before /v3 Pion WebRTC would gather all candidates before a CreateOffer or CreateAnswer generated a SDP. This would cause a few issues in real world applications. You can read about the benefits of Trickle ICE here

  • Longer call connection times since we blocked for STUN/TURN even if not needed
  • This didn't comply with the WebRTC spec
  • Made it harder for users to filter/process ICE Candidates

Now you should exchange ICE Candidates that are pushed via the OnICECandidate callback.

Before

  peerConnection, _ := webrtc.NewPeerConnection(webrtc.Configuration{})

  offer, _ := peerConnection.CreateOffer()
  peerConnection.SetLocalDescription(offer)

  // Send `offer` to remote peer
  websocket.Write(offer)

After

  peerConnection, _ := webrtc.NewPeerConnection(webrtc.Configuration{})

  // Set ICE Candidate handler. As soon as a PeerConnection has gathered a candidate
  // send it to the other peer
  peerConnection.OnICECandidate(func(i *webrtc.ICECandidate) {
    // Send ICE Candidate via Websocket/HTTP/$X to remote peer
  })

  // Listen for ICE Candidates from the remote peer
  peerConnection.AddICECandidate(remoteCandidate)

  // You still signal like before, but `CreateOffer` will be much faster
  offer, _ := peerConnection.CreateOffer()
  peerConnection.SetLocalDescription(offer)

  // Send `offer` to remote peer
  websocket.Write(offer)

If you are unable to migrate we have provided a helper function to simulate the pre-v3 behavior.

Helper function to simulate non-trickle ICE

  peerConnection, _ := webrtc.NewPeerConnection(webrtc.Configuration{})

  offer, _ := peerConnection.CreateOffer()

  // Create channel that is blocked until ICE Gathering is complete
  gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
  peerConnection.SetLocalDescription(offer)
  <-gatherComplete

  // Send `LocalDescription` to remote peer
  // This is the offer but populated with all the ICE Candidates
  websocket.Write(*peerConnection.LocalDescription())

This was changed with bb3aa9

A data channel is no longer implicitly created with a PeerConnection

Before /v3 Pion WebRTC would always insert a application Media Section. This means that an offer would work even if you didn't create a DataChannel or Transceiver, in /v3 you MUST create a DataChannel or track first. To better illustrate these are two SDPs, each from a different version of Pion WebRTC

/v2 SDP with no CreateDataChannel

v=0
o=- 8334017457074456852 1596089329 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 91:B0:3A:6E:9E:43:9A:9D:1B:71:17:7D:FB:D0:5C:81:12:6E:61:D5:6C:BF:92:E8:8D:04:F5:92:EF:62:36:C9
a=group:BUNDLE 0
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=setup:actpass
a=mid:0
a=sendrecv
a=sctpmap:5000 webrtc-datachannel 1024
a=ice-ufrag:yBlrlyMmuDdCfawp
a=ice-pwd:RzlouYCNYDNpPLJLdddFtUkMVpKVLYWz
a=candidate:foundation 1 udp 2130706431 192.168.1.8 51147 typ host generation 0
a=candidate:foundation 2 udp 2130706431 192.168.1.8 51147 typ host generation 0
a=end-of-candidates

/v3 SDP with no CreateDataChannel

v=0
o=- 8628031010413059766 1596089396 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 64:79:7C:73:6B:8A:CF:34:9D:D0:9C:6B:31:07:44:0A:CD:56:F0:74:62:72:D4:23:D5:BC:B2:C9:46:55:C5:A3
a=group:BUNDLE

To simulate the old functionality, call CreateDataChannel after creating your PeerConnection and before calling anything else.

This was changed with abd6a3

Track is now an interface

The design of the Track API in /v3 has been updated to accommodate more use cases and reduce the sharp edges in the API. Before we used one structure to represent incoming and outgoing media. This didn't match with how WebRTC actually works. In WebRTC a track isn't bi-directional. Having Read and Write on the same structure was confusing.

Split Track into TrackLocal and TrackRemote

Now we have TrackLocal and TrackRemote. TrackLocal is used to send media, TrackRemote is used to receive media.

TrackRemote has a similar API to /v2. It has Read and ReadRTP and code will continue to work with just a name change Track -> TrackRemote

TrackLocal is now an interface, and will require more work to port. For existing code you will want to use one of the TrackLocal implementations. NewLocalTrackStaticSample or NewLocalTrackStaticRTP depending on what type of data you were sending before.

Code that looks like

  videoTrack, err := peerConnection.NewTrack(payloadType, randutil.NewMathRandomGenerator().Uint32(), "video", "pion")

Needs to become like one of the following

  videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: "video/vp8"}, "video", "pion")
  videoTrack, err := webrtc.NewTrackLocalStaticRTP(webrtc.RTPCodecCapability{MimeType: "video/vp8"}, "video", "pion")

Users no longer have to manage SSRC/PayloadType

When creating a Track you don't need to know these values. When writing packets you don't need to pull these values either. Internally we make sure that everything is properly set. This means that mediaengine.PopulateFromSDP has been removed, and you can delete any code that does this.

Other packages can satisfy LocalTrack

pion/mediadevices now can provide an API that feels like getUserMedia in the browser. Before it wasn't able to generate anything that pion/webrtc could directly call AddTrack on.

A user could also implement LocalTrack and and add custom behavior.

MediaEngine API has changed

We now use data structures from the W3C to configure available codecs and header extensions. You can also define your own MimeTypes, allowing you to send any codec you wish! pion/webrtc can support for a new codec with just calls to the public API.

Before

  m.RegisterCodec(webrtc.NewRTPOpusCodec(webrtc.DefaultPayloadTypeOpus, 48000))
  m.RegisterCodec(webrtc.NewRTPVP8Codec(webrtc.DefaultPayloadTypeVP8, 90000))

After

  if err := m.RegisterCodec(webrtc.RTPCodecParameters{
    RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: "video/VP8", ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
    PayloadType:        96,
  }, webrtc.RTPCodecTypeVideo); err != nil {
    panic(err)
  }
  if err := m.RegisterCodec(webrtc.RTPCodecParameters{
    RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: "audio/opus", ClockRate: 48000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
    PayloadType:        111,
  }, webrtc.RTPCodecTypeAudio); err != nil {
    panic(err)
  }

This was changed with 7edfb7

New Features

ICE Restarts

You can now initiate and accept an ICE Restart! This means that if a PeerConnection goes to Disconnected or Failed because of network interruption it is no longer fatal.

To use you just need to pass ICERestart: true in your OfferOptions. The answering PeerConnection will then restart also. This is supported in FireFox/Chrome and Mobile WebRTC Clients.

  peerConn, _ := NewPeerConnection(Configuration{})

  // PeerConnection goes to ICEConnectionStateFailed

  offer, _ := peerConn.CreateOffer(&OfferOptions{ICERestart: true})

This was implemented in f29414

Interceptors

v3.0.0 introduces a new Pion specific concept called interceptors. Interceptors are pluggable RTP/RTCP processesors. Via a public API users can easily add and customize operations that are run on inbound/outbound RTP. Interceptors are an interface this means A user could provide their own implementation. Or you can use one of the interceptors Pion will have in-tree.

We designed this with the following vision.

  • Useful defaults. Nontechnical users should be able to build things without tuning.
  • Don't block unique use cases. We shouldn't paint ourself in a corner. We want to support interesting WebRTC users
  • Allow users to bring their own logic. We should encourage easy changing. Innovation in this area is important.
  • Allow users to learn. Don't put this stuff deep in the code base. Should be easy to jump into so people can learn.

These are the use cases this API was designed support.

  • FEC

    • Apply FEC, allow user to choose between trade-offs
  • NACK Responder

    • Respond to inbound NACKs, with user customizable buffer size
  • JitterBuffer

    • Applying delay/re-ordering
    • Sending NACK
  • Congestion Control

    • Generate Sender/Receiver/Transport Wide Congestion Control Reports
    • Process these reports and provide BWE
  • Stats

    • Process the inbound/outbound packets and provide analysis of the RTP stream

Clone this wiki locally