Bandwidth Management

muaz-khan edited this page Oct 17, 2014 · 1 revision

This wiki page explains bandwidth usage in RTCMultiConnection applications and how to "reliably" control it for both audio and video tracks.

This page also explains how to check for available bandwidth, and how to provide solutions like "adaptive bandwidth usage" and "variable bandwidth usage".

Factors that affects bandwidth usage

  1. Video resolutions
  2. RTP-packets drop and re-transmission
  3. RTT and renegotiation

How to set b=AS for video tracks?

Reference doc:

connection.bandwidth = {
    video: 256,    // 256kbps
    screen: 300    // 300kbps
};

How to force lowest possible video bandwidth?

connection.bandwidth = {
    video: 20
};

var videoConstraints = {
    mandatory: {
        minWidth: 320,
        maxWidth: 320,
        minHeight: 180,
        maxHeight: 180
    },
    optional: []
};

connection.mediaConstraints = {
    video: videoConstraints,
    audio: true
};

How to set b=AS for audio tracks?

connection.bandwidth = {
    audio: 50 // lowest possible value is 30
};

To get better audio output:

connection.bandwidth = {
    audio: 128    // 128kbps
};

Opus codec and maxaveragebitrate

Reference doc:

connection.processSdp = function (sdp) {
    sdp = addStereo(sdp);
    return sdp;
};

function addStereo(sdp) {
    var sdpLines = sdp.split('\r\n');

    // Find opus payload.
    var opusIndex = findLine(sdpLines, 'a=rtpmap', 'opus/48000');
    var opusPayload;
    if (opusIndex) {
        opusPayload = getCodecPayloadType(sdpLines[opusIndex]);
    }

    // Find the payload in fmtp line.
    var fmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + opusPayload.toString());
    if (fmtpLineIndex === null) {
        return sdp;
    }

    // Append stereo=1 to fmtp line.
    // added maxaveragebitrate here; about 128 kbits/s
    // added stereo=1 here for stereo audio
    sdpLines[fmtpLineIndex] = sdpLines[fmtpLineIndex].concat('; stereo=1; maxaveragebitrate=' + (128 * 1024));

    sdp = sdpLines.join('\r\n');
    return sdp;
}

// Find the line in sdpLines that starts with |prefix|, and, if specified,
// contains |substr| (case-insensitive search).
function findLine(sdpLines, prefix, substr) {
    return findLineInRange(sdpLines, 0, -1, prefix, substr);
}

// Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
// and, if specified, contains |substr| (case-insensitive search).
function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
    var realEndLine = endLine !== -1 ? endLine : sdpLines.length;
    for (var i = startLine; i < realEndLine; ++i) {
        if (sdpLines[i].indexOf(prefix) === 0) {
            if (!substr ||
                sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
                return i;
            }
        }
    }
    return null;
}

// Gets the codec payload type from an a=rtpmap:X line.
function getCodecPayloadType(sdpLine) {
    var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
    var result = sdpLine.match(pattern);
    return (result && result.length === 2) ? result[1] : null;
}

maxaveragebitrate works in stable and beta channels in chrome, but b=AS only works in canary.

That's why you need to apply both.

A few experimental bitrate SDP attributes

Ref:

x-google-min-bitrate=1000
x-google-max-bitrate=2500
x-google-max-quantization=56

You can inject this SDP-line using processSdp method:

How to check available bandwidth?

It isn't easy to reliably check available bandwidth in a javascript application. RTCPeerConnection getStats API also doesn't helps to detect "exact-available-bandwidth":

Factors that causes it much difficult to detect exact available bandwidth:

  1. TCP/UDP overhead and "variable" latency
  2. RTP packets lost and re-transmission
  3. RTT drops and re-transmission

That's why getStats API isn't having correct values for bitsSentPerSecond and bitsReceivedPerSecond.

Demos

  1. https://www.webrtc-experiment.com/RTCMultiConnection/bandwidth.html?audio=30&video=30

P.S. This wiki page is expected to be updated soon with working snippets and examples.