tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RTCEncodedFrame-timestamps-helper.js (4170B)


      1 'use strict';
      2 
      3 // This file depends on `webrtc/RTCPeerConnection-helper.js`
      4 // which should be loaded from the main HTML file.
      5 
      6 // TODO: Replace with IETF link.
      7 var kAbsCaptureTime =
      8    'http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time';
      9 
     10 function addHeaderExtensionToSdp(sdp, uri) {
     11  // Find the highest used header extension id by sorting the extension ids
     12  // used, eliminating duplicates and adding one. This is not quite correct but
     13  // this code will go away with the header extension API.
     14  const usedIds =
     15      sdp.split('\n')
     16          .filter(line => line.startsWith('a=extmap:'))
     17          .map(line => parseInt(line.split(' ')[0].substring(9), 10))
     18          .sort((a, b) => a - b)
     19          .filter((item, index, array) => array.indexOf(item) === index);
     20  const nextId = usedIds[usedIds.length - 1] + 1;
     21  const extmapLine = 'a=extmap:' + nextId + ' ' + uri + '\r\n';
     22 
     23  const sections = sdp.split('\nm=').map((part, index) => {
     24    return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
     25  });
     26  const sessionPart = sections.shift();
     27  return sessionPart +
     28      sections.map(mediaSection => mediaSection + extmapLine).join('');
     29 }
     30 
     31 async function addAbsCaptureTimeAndExchangeOffer(caller, callee) {
     32  let offer = await caller.createOffer();
     33 
     34  // Absolute capture time header extension may not be offered by default,
     35  // in such case, munge the SDP.
     36  offer.sdp = addHeaderExtensionToSdp(offer.sdp, kAbsCaptureTime);
     37 
     38  await caller.setLocalDescription(offer);
     39  return callee.setRemoteDescription(offer);
     40 }
     41 
     42 async function checkAbsCaptureTimeAndExchangeAnswer(
     43    caller, callee, absCaptureTimeAnswered) {
     44  let answer = await callee.createAnswer();
     45 
     46  const extmap = new RegExp('a=extmap:\\d+ ' + kAbsCaptureTime + '\r\n', 'g');
     47  if (answer.sdp.match(extmap) == null) {
     48    // We expect that absolute capture time RTP header extension is answered.
     49    // But if not, there is no need to proceed with the test.
     50    assert_false(
     51        absCaptureTimeAnswered,
     52        'Absolute capture time RTP ' +
     53            'header extension is not answered');
     54  } else {
     55    if (!absCaptureTimeAnswered) {
     56      // We expect that absolute capture time RTP header extension is not
     57      // answered, but it is, then we munge the answer to remove it.
     58      answer.sdp = answer.sdp.replace(extmap, '');
     59    }
     60  }
     61 
     62  await callee.setLocalDescription(answer);
     63  return caller.setRemoteDescription(answer);
     64 }
     65 
     66 async function exchangeOfferAndListenToOntrack(
     67    t, caller, callee, absCaptureTimeOffered) {
     68  const ontrackPromise = addEventListenerPromise(t, callee, 'track');
     69  // Absolute capture time header extension is expected not offered by default,
     70  // and thus munging is needed to enable it.
     71  await absCaptureTimeOffered ?
     72      addAbsCaptureTimeAndExchangeOffer(caller, callee) :
     73      exchangeOffer(caller, callee);
     74  return ontrackPromise;
     75 }
     76 
     77 async function initiateCall(
     78    t, streamOptions, enableAbsCaptureTime, worker, enableSenderTransform,
     79    enableReceiverTransform) {
     80  const caller = new RTCPeerConnection();
     81  t.add_cleanup(() => caller.close());
     82  const callee = new RTCPeerConnection();
     83  t.add_cleanup(() => callee.close());
     84  const senderTransform = enableSenderTransform ?
     85      new RTCRtpScriptTransform(worker, {name: 'sender'}) :
     86      null;
     87  const receiverTransform = enableReceiverTransform ?
     88      new RTCRtpScriptTransform(worker, {name: 'receiver'}) :
     89      null;
     90 
     91 
     92  const stream = await getNoiseStream(streamOptions);
     93  stream.getTracks().forEach(track => {
     94    const sender = caller.addTrack(track, stream);
     95    if (enableSenderTransform) {
     96      sender.transform = senderTransform;
     97    }
     98    t.add_cleanup(() => track.stop());
     99  });
    100 
    101  callee.ontrack =
    102      e => {
    103        if (enableReceiverTransform) {
    104          e.receiver.transform = receiverTransform;
    105        }
    106      }
    107 
    108  exchangeIceCandidates(caller, callee);
    109 
    110  await exchangeOfferAndListenToOntrack(
    111      t, caller, callee, enableAbsCaptureTime);
    112 
    113  // Exchange answer and check whether the absolute capture time RTP header
    114  // extension is answered.
    115  await checkAbsCaptureTimeAndExchangeAnswer(
    116      caller, callee, enableAbsCaptureTime);
    117 }