DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
<!DOCTYPE HTML>
<html>
<head>
  <script type="application/javascript" src="pc.js"></script>
  <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
  createHTML({
    bug: "1432793",
    title: "Simulcast with odd resolution",
    visible: true
  });

  const encodings = [{ rid: "foo", maxBitrate: 40000, scaleResolutionDownBy: 1.9 },
                     { rid: "bar", maxBitrate: 40000, scaleResolutionDownBy: 3.5 },
                     { rid: "baz", maxBitrate: 40000, scaleResolutionDownBy: 17.8 }];

  function addRIDExtension(pc, extensionId) {
    const receivers = pc._pc.getReceivers();
    is(receivers.length, 1, "We have exactly one RTP receiver");
    const receiver = receivers[0];

    SpecialPowers.wrap(pc._pc).mozAddRIDExtension(receiver, extensionId);
  }

  function selectRecvRID(pc, rid) {
    const receivers = pc._pc.getReceivers();
    is(receivers.length, 1, "We have exactly one RTP receiver");
    const receiver = receivers[0];

    SpecialPowers.wrap(pc._pc).mozAddRIDFilter(receiver, rid);
  }

  async function changeSourceResolution(test, emitter, width, height) {
    info(`Changing source resolution to ${width}x${height}`);
    emitter.size(width, height);
    emitter.start();
    await Promise.all([
        haveEvent(test.pcRemote.localMediaElements[0], "resize"),
        haveEvent(test.pcLocal.remoteMediaElements[0], "resize"),
    ]);
    emitter.stop();
    info("Source resolution changed");
  }

  async function setParameters(test, emitter, encodings) {
    info(`Setting parameters to ${JSON.stringify(encodings)}`);
    emitter.start();
    await test.pcRemote._pc.getSenders()[0].setParameters({encodings});
    await haveEvent(test.pcLocal.remoteMediaElements[0], "resize");
    emitter.stop();
		info("Parameters set");
	}

  async function checkResolution(test, emitter, rid) {
    const vlocal = test.pcRemote.localMediaElements[0];
    const vremote = test.pcLocal.remoteMediaElements[0];

    info(`Changing to rid ${rid}`);
    selectRecvRID(test.pcLocal, rid);
    emitter.start();
    await haveEvent(vremote, "resize");
    emitter.stop();

    const srcWidth = vlocal.videoWidth;
    const srcHeight = vlocal.videoHeight;
    info(`Source resolution is ${srcWidth}x${srcHeight}`);

    const scaleDownBy = encodings.find(({rid: r}) => r == rid).scaleResolutionDownBy;
    const expectedWidth = srcWidth / scaleDownBy;
    const expectedHeight = srcHeight / scaleDownBy;
    const margin = srcWidth * 0.1;
    const width = vremote.videoWidth;
    const height = vremote.videoHeight;
    ok(width >= expectedWidth - margin && width <= expectedWidth + margin,
      `Width ${width} should be within 10% of ${expectedWidth} for rid '${rid}'`);
    ok(height >= expectedHeight - margin && height <= expectedHeight + margin,
      `Height ${height} should be within 10% of ${expectedHeight} for rid '${rid}'`);
  }

  async function checkResolutions(test, emitter) {
    const vremote = test.pcLocal.remoteMediaElements[0];

    // Start by making sure we're not on foo (first default) or
    // baz (subsequent default), thus getting resize events.
    selectRecvRID(test.pcLocal, "bar");
    emitter.start();
    await haveEvent(vremote, "resize");
    emitter.stop();

    await checkResolution(test, emitter, "foo");
    await checkResolution(test, emitter, "bar");
    await checkResolution(test, emitter, "baz");
  }

  runNetworkTest(async () => {
    await pushPrefs(['media.peerconnection.simulcast', true],
                    ['media.peerconnection.video.lock_scaling', true],
                    // 240Kbps was determined empirically
                    ['media.peerconnection.video.min_bitrate_estimate', 240*1000]);

    let emitter, helper;

    test = new PeerConnectionTest({bundle: false});
    test.setMediaConstraints([{video: true}], [{video: true}]);

    test.chain.replace("PC_REMOTE_GUM", [
      function PC_REMOTE_CANVAS_CAPTURESTREAM(test) {
        helper = new VideoStreamHelper();
        emitter = new VideoFrameEmitter(helper.green, helper.red, 705, 528);
        test.pcRemote.attachLocalStream(emitter.stream());
        emitter.start();
      }
    ]);

    test.chain.insertAfter('PC_REMOTE_GET_OFFER', [
      function PC_REMOTE_SET_RIDS(test) {
        const senders = test.pcRemote._pc.getSenders();
        is(senders.length, 1, "We have exactly one RTP sender");
        const sender = senders[0];
        ok(sender.track, "Sender has a track");

        return sender.setParameters({encodings});
      },
      async function PC_LOCAL_ADD_RIDS_TO_OFFER(test) {
        // Create a dummy offer, and use it to set simulcast stuff on the
        // offer we will actually be using.
        let offer = await test.createOffer(test.pcRemote);
        test._local_offer.sdp = sdputils.transferSimulcastProperties(
            offer.sdp, test._local_offer.sdp);
        info(`Offer with RIDs: ${JSON.stringify(test._local_offer)}`);
        ok(test._local_offer.sdp.match(/a=simulcast:/), "Modified offer has simulcast");
        ok(test._local_offer.sdp.match(/a=rid:foo/), "Modified offer has rid foo");
        ok(test._local_offer.sdp.match(/a=rid:bar/), "Modified offer has rid bar");
        ok(test._local_offer.sdp.match(/a=rid:baz/), "Modified offer has rid bar");
        ok(test._local_offer.sdp.match(/urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/), "Modified offer has RID");
      }
    ]);

    test.chain.insertAfter('PC_LOCAL_GET_ANSWER',[
      function PC_LOCAL_REMOVE_SIMULCAST_ATTRS_FROM_ANSWER(test) {
        test._remote_answer.sdp =
          sdputils.removeSimulcastProperties(test._remote_answer.sdp);
      }
    ]);

    // do this after set remote description so the MediaPipeline
    // has been created.
    test.chain.insertAfter('PC_LOCAL_SET_REMOTE_DESCRIPTION',[
      function PC_LOCAL_SET_RTP_FIRST_RID(test) {
        info(`local offer: ${test._local_offer.sdp}`);
        const extmap_id = test._local_offer.sdp.match(
            "a=extmap:([0-9+])/recvonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
        ok(extmap_id, `Original answer has extmap id for simulcast: ${extmap_id[1]}`);
        // Cause pcLocal to filter out everything but RID "foo", only
        // allowing one of the simulcast streams through.
        addRIDExtension(test.pcLocal, extmap_id[1]);
        selectRecvRID(test.pcLocal, "foo");
      },
      function SETUP_RESIZE_LISTENERS(test) {
        for(const elem of [...test.pcRemote.localMediaElements,
                           ...test.pcLocal.remoteMediaElements,
                          ]) {
          elem.addEventListener("resize",
            () => info(`element ${elem.id} resized to ${elem.videoWidth}x${elem.videoHeight}`));
        }
      },
    ]);

    test.chain.append([
      async function PC_LOCAL_CHECK_INITIAL_SIZES() {
        await checkResolutions(test, emitter);
      },
      async function PC_LOCAL_CHANGE_SRC_1() {
        await changeSourceResolution(test, emitter, 1280, 720);
        await checkResolutions(test, emitter);
      },
      async function PC_LOCAL_CHANGE_PARAMS_2() {
        encodings.find(({rid}) => rid == "foo").scaleResolutionDownBy = 1;
        encodings.find(({rid}) => rid == "bar").scaleResolutionDownBy = 2;
        encodings.find(({rid}) => rid == "baz").scaleResolutionDownBy = 3;
        await setParameters(test, emitter, encodings);
        await checkResolutions(test, emitter);
      },
    ]);

    await test.run();
  });
</script>
</pre>
</body>
</html>