rtc-sdp
Version:
rtc.io utility module for patching (munging) SDP
154 lines (121 loc) • 4 kB
JavaScript
/* jshint node: true */
;
var nub = require('whisk/nub');
var pluck = require('whisk/pluck');
var flatten = require('whisk/flatten');
var reLineBreak = /\r?\n/;
var reTrailingNewlines = /\r?\n$/;
// list sdp line types that are not "significant"
var nonHeaderLines = [ 'a', 'c', 'b', 'k' ];
var parsers = require('./parsers');
/**
# rtc-sdp
This is a utility module for intepreting and patching sdp.
## Usage
The `rtc-sdp` main module exposes a single function that is capable of
parsing lines of SDP, and providing an object allowing you to perform
operations on those parsed lines:
```js
var sdp = require('rtc-sdp')(lines);
```
The currently supported operations are listed below:
**/
module.exports = function(sdp) {
var ops = {};
var parsed = [];
var activeCollector;
// initialise the lines
var lines = sdp.split(reLineBreak).filter(Boolean).map(function(line) {
return line.split('=');
});
var inputOrder = nub(lines.filter(function(line) {
return line[0] && nonHeaderLines.indexOf(line[0]) < 0;
}).map(pluck(0)));
var findLine = ops.findLine = function(type, index) {
var lineData = parsed.filter(function(line) {
return line[0] === type;
})[index || 0];
return lineData && lineData[1];
};
// push into parsed sections
lines.forEach(function(line) {
var customParser = parsers[line[0]];
if (customParser) {
activeCollector = customParser(parsed, line);
}
else if (activeCollector) {
activeCollector = activeCollector(line);
}
else {
parsed.push(line);
}
});
/**
### `sdp.addIceCandidate(data)`
Modify the sdp to include candidates as denoted by the data.
**/
ops.addIceCandidate = function(data) {
var lineIndex = (data || {}).lineIndex || (data || {}).sdpMLineIndex;
var mLine = typeof lineIndex != 'undefined' && findLine('m', lineIndex);
var candidate = (data || {}).candidate;
// if we have the mLine add the new candidate
if (mLine && candidate) {
mLine.childlines.push(candidate.replace(reTrailingNewlines, '').split('='));
}
};
/**
### `sdp.getMediaTypes() => []`
Retrieve the list of media types that have been defined in the sdp via
`m=` lines.
**/
ops.getMediaTypes = function() {
function getMediaType(data) {
return data[1].def.split(/\s/)[0];
}
return parsed.filter(function(parts) {
return parts[0] === 'm' && parts[1] && parts[1].def;
}).map(getMediaType);
};
/**
### `sdp.getMediaIDs() => []`
Returns the list of unique media line IDs that have been defined in the sdp
via `a=mid:` lines.
**/
ops.getMediaIDs = function() {
return parsed.filter(function(parts) {
return parts[0] === 'm' && parts[1] && parts[1].childlines && parts[1].childlines.length > 0;
}).map(function(mediaLine) {
var lines = mediaLine[1].childlines;
// Default ID to the media type
var mediaId = mediaLine[1].def.split(/\s/)[0];
// Look for the media ID
for (var i = 0; i < lines.length; i++) {
var tokens = lines[i][1].split(':');
if (tokens.length > 0 && tokens[0] === 'mid') {
mediaId = tokens[1];
break;
}
}
return mediaId;
});
};
/**
### `sdp.toString()`
Convert the SDP structure that is currently retained in memory, into a string
that can be provided to a `setLocalDescription` (or `setRemoteDescription`)
WebRTC call.
**/
ops.toString = function() {
return parsed.map(function(line) {
return typeof line[1].toArray == 'function' ? line[1].toArray() : [ line ];
}).reduce(flatten).map(function(line) {
return line.join('=');
}).join('\r\n') + '\r\n';
};
/**
## SDP Filtering / Munging Functions
There are additional functions included in the module to assign with
performing "single-shot" SDP filtering (or munging) operations:
**/
return ops;
};