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
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102

content / test / data / media / peerconnection-source-feed-switch.html [blame]

<html>
<body id="body">
    <h1>WebRTC Feed Switch Test</h1>
    <p>Status: <span id="status">not-started</span></p>
</body>
<script type="text/javascript" src="webrtc_test_utilities.js"></script>
<script type="text/javascript" src="peerconnection-multiple-streams.js"></script>
<script type="text/javascript">
const $ = document.getElementById.bind(document);

const MAIN_FEED_RESOLUTION = {w:1280, h:720};

// This resolution is typical for a small feed in a video call.
const SMALL_FEED_RESOLUTION = {w:182, h:136};

class TestRunner {
  constructor(numConnections, runtimeSeconds, iterationDelayMillis) {
    this.runtimeSeconds = runtimeSeconds;
    this.iterationDelayMillis = iterationDelayMillis;
    this.videoElements = [];
    this.mainFeed = null;
    this.peerConnections = [];
    this.numConnections = numConnections;
    this.iteration = 0;
    this.startTime = 0;  // initialized to dummy value
    this.status = this.getStatusInternal_();
  }

  runTest() {
    for (let i = 0; i < this.numConnections; i++) {
      const videoElement = document.createElement('video');
      videoElement.autoplay = true;
      $('body').appendChild(videoElement);
      if (!this.mainFeed) {
        // The first created is the main feed.
        setSize(videoElement, MAIN_FEED_RESOLUTION);
        this.mainFeed = videoElement;
      } else {
        setSize(videoElement, SMALL_FEED_RESOLUTION);
        this.videoElements.push(videoElement);
      }
      this.peerConnections.push(new PeerConnection(
          videoElement, [MAIN_FEED_RESOLUTION]));
    }
    const promises = this.peerConnections.map((conn) => conn.start());
    return Promise.all(promises)
        .then(() => {
          this.startTime = Date.now();
          return this.switchFeedLoop();
        })
        .then(logSuccess);
  }

  switchFeedLoop() {
    this.iteration++;
    this.status = this.getStatusInternal_();
    $('status').textContent = this.status;
    if (this.status == 'ok-done') {
      return;
    }
    const switchWith = Math.floor(Math.random() * this.videoElements.length);
    const newMainSrc = this.videoElements[switchWith].srcObject;
    this.videoElements[switchWith].srcObject = this.mainFeed.srcObject;
    this.mainFeed.srcObject = newMainSrc;
    return new Promise(resolve => {
      setTimeout(resolve, this.iterationDelayMillis);
    })
    .then(() => this.switchFeedLoop());
  }

  getStatus() {
    return this.status;
  }

  getStatusInternal_() {
    if (this.iteration == 0) {
      return 'not-started';
    }
    const timeSpent = Date.now() - this.startTime;
    if (timeSpent >= this.runtimeSeconds * 1000) {
      return 'ok-done';
    } else {
      return `running, iteration: ${this.iteration}`;
    }
  }
}

function setSize(element, size) {
  element.setAttribute('style', `width:${size.w}px;height:${size.h}px`);
}

function startTest(
    runtimeSeconds, numPeerConnections, iterationDelayMillis) {
  const testRunner = new TestRunner(
      numPeerConnections, runtimeSeconds, iterationDelayMillis);
  return testRunner.runTest();
}

function getStatus() {
  return testRunner ? testRunner.getStatus() : 'not-initialized';
}
</script>