• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer
webrtcHacks

webrtcHacks

Guides and information for WebRTC developers

  • Home
  • About
    • Chad Hart
    • Philipp Hancke
  • Subscribe
  • Contact
  • Show Search
Hide Search

Guide ORTC, Philipp Hancke, Walkthrough Philipp Hancke · September 18, 2015

First steps with ORTC

ORTC support in Edge has been announced today. A while back, we saw this on twitter:

Windows Insider Preview build 10525 is now available for PCs: http://t.co/zeXQJocgLs This release lays groundwork for ORTC in Microsoft Edge

— Microsoft Edge Dev (@MSEdgeDev) August 18, 2015

“This release [build 10525] lays the groundwork for ORTC” was quite an understatement. It was considered experimental and while the implementation still differs from the specification (which is still work in progress) slightly, it already worked and as a developer you can get familiar with how ORTC works and how it is different from the RTCPeerConnection API.
If you want to test this, please use builds newer than 10547. Join the Windows Insider Program to get them and make sure you’re on the fast ring.

The approach taken differs from the RTCPeerConnection way of giving you a blob that you exchange as this WebRTC PC1 sample shows quite well. It’s more about giving you the building blocks.

Lego Bricks, courtesy of Wikipedia

In ORTC, you have to incrementally build up things. Let’s walk through the code (available on github):

Setting up a Peer to Peer connection

JavaScript
1
2
3
var gatherer1 = new RTCIceGatherer(iceOptions);
var transport1 = new RTCIceTransport(gatherer1);
var dtls1 = new RTCDtlsTransport(transport1);

There are three elements on the transport side:

  1. RTCIceGatherer –  gathers ICE candidates to be sent to the peer
  2. RTCIceTransport – where you add the candidates from the peer
  3. DtlsTransport –  sits on top of the ICE transport and deals with encryption.

As in the peerConnection API, you exchange the candidates:

JavaScript
1
2
3
4
5
6
7
8
9
// Exchange ICE candidates.
gatherer1.onlocalcandidate = function (evt) {
    console.log('1 -> 2', evt.candidate);
    transport2.addRemoteCandidate(evt.candidate);
};
gatherer2.onlocalcandidate = function (evt) {
    console.log('2 -> 1', evt.candidate);
    transport1.addRemoteCandidate(evt.candidate);
};

Also, you need to exchange the ICE parameters (usernameFragment and password) and start the ICE transport:

JavaScript
1
2
3
4
transport1.start(gatherer1, gatherer2.getLocalParameters(), 'controlling');
transport1.onicestatechange = function() {
  console.log('ICE transport 1 state change', transport1.state);
};

This is done with SDP in the PeerConnection API. One side needs to be controlling, the other is controlled.

You also need to start the DTLS transport with the remote fingerprint and hash algorithm:

JavaScript
1
2
3
4
dtls1.start(dtls2.getLocalParameters());
dtls1.ondtlsstatechange = function() {
  console.log('DTLS transport 1 state change', dtls1.state);
};

Once this is done, you can see the candidates being exchanged and the ICE and DTLS state changes on both sides.

Cool. Now what?

Sending a MediaStream track over the connection

Let’s send a MediaStream track. First, we acquire it using the promise-based navigator.mediaDevices.getUserMedia API and attach it to the local video element.

JavaScript
1
2
3
4
// call getUserMedia to get a MediaStream.
navigator.mediaDevices.getUserMedia({video: true})
.then(function(stream) {
  document.getElementById('localVideo').srcObject = stream;

Next, we determine the send and receive parameters. This is where the PeerConnection API does the “offer/answer” magic.
Since our sending capabilities match the receiving capabilities, there is little we need to do here.
Some black magic is still involved, check the specification for the gory details.

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  // Determine RtpCodecParameters. Consider this black magic.
  var params = RTCRtpReceiver.getCapabilities('video');
  params.muxId = 1001;
  params.encodings = [{
    ssrc: 1001,
    codecPayloadType: 0,
    fec: 0,
    rtx: 0,
    priority: 1.0,
    maxBitrate: 2000000.0,
    minQuality: 0,
    framerateBias: 0.5,
    resolutionScale: 1.0,
    framerateScale: 1.0,
    active: true,
    dependencyEncodingId: undefined,
    encodingId: undefined
  }];
 
  // We need to transform the codec capability into a codec.
  params.codecs.forEach(function (codec) {
    codec.payloadType = codec.preferredPayloadType;
  });
  params.rtcp = {
    cname: "",
    reducedSize: false,
    ssrc: 0,
    mux: true
  };
  console.log(params);

Then, we start the RtpReceiver with those parameters:

JavaScript
1
2
3
4
5
6
  // Start the RtpReceiver to receive the track.
  receiver = new RTCRtpReceiver(dtls2, 'video');
  receiver.receive(params);
  var remoteStream = new MediaStream();
  remoteStream.addTrack(receiver.track);
  document.getElementById('remoteVideo').srcObject = remoteStream;

Note that the Edge implementation is slightly different from the current ORTC specification here since you need to specify the media type as second argument when creating the RtpReceiver.
We create a stream to contain the track and attach it to the remote video element.
Last but not least, let’s send the video track we got:

JavaScript
1
2
  sender = new RTCRtpSender(stream.getVideoTracks()[0], dtls1);
  sender.send(params);

That’s it. It gets slightly more complicated when you have to deal with multiple tracks, and have to actually negotiate capabilities in order to interop between Chrome and Edge. But that’s a longer story…

{“author”: “Philipp Hancke“}

Guide ORTC, Philipp Hancke, Walkthrough

Related Posts

  • WebRTC Today & Tomorrow: Interview with W3C WebRTC Chair Bernard AbobaWebRTC Today & Tomorrow: Interview with W3C WebRTC Chair Bernard Aboba
  • Using getDisplayMedia for local recording with audio on JitsiUsing getDisplayMedia for local recording with audio on Jitsi
  • Accelerated Computer Vision inside a WebRTC Media Server with Intel OWTAccelerated Computer Vision inside a WebRTC Media Server with Intel OWT
  • First steps with QUIC DataChannelsFirst steps with QUIC DataChannels

RSS Feed

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

  • Sponsored. Become a webtcHacks sponsor

Email Subscription

Subscribe to our mailing list

* indicates required

Twittering

Tweets by @webRTChacks
webrtcHacksguides and information for WebRTC developers

Footer

SITE

  • Post List
  • About
  • Contact

Categories

  • Guide
  • Other
  • Reverse-Engineering
  • Standards
  • Technology

Tags

apple Blackbox Exploration Brief camera Chrome code computer vision DataChannel debug e2ee Edge extension gateway getUserMedia ICE ims insertable streams ios ip leakage janus jitsi MCU Microsoft NAT opensource Opus ORTC Promo Q&A raspberry pi Safari SDES SDP sfu signaling simulcast standards TURN video vp8 w3c Walkthrough Web Audio webrtc-internals wireshark

Follow

  • Twitter
  • YouTube
  • GitHub
  • RSS

webrtcHacks · copyright © 2023