/* * Spreed Speak Freely. * Copyright (C) 2013-2014 struktur AG * * This file is part of Spreed Speak Freely. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * */ define(['jquery', 'underscore'], function($, _) { var Utils = function() { } Utils.prototype.mergeConstraints = function(cons1, cons2) { var merged = cons1; var name; for (name in cons2.mandatory) { merged.mandatory[name] = cons2.mandatory[name]; } merged.optional.concat(cons2.optional); return merged; }; Utils.prototype.extractSdp = function(sdpLine, pattern) { var result = sdpLine.match(pattern); return (result && result.length == 2)? result[1]: null; }; Utils.prototype.addStereo = function(sdp) { // Set Opus in Stereo. var sdpLines = sdp.split('\r\n'); var opusPayload = ""; var fmtpLineIndex = null; var i; // Find opus payload. for (i=0; i < sdpLines.length; i++) { if (sdpLines[i].search('opus/48000') !== -1) { opusPayload = this.extractSdp(sdpLines[i], /:(\d+) opus\/48000/i); break; } } // Find the payload in fmtp line. for (i=0; i < sdpLines.length; i++) { if (sdpLines[i].search('a=fmtp') !== -1) { var payload = this.extractSdp(sdpLines[i], /a=fmtp:(\d+)/ ); if (payload === opusPayload) { fmtpLineIndex = i; break; } } } // No fmtp line found. if (fmtpLineIndex === null) { console.log("Unable to add stereo (no fmtp line for opus payload)", opusPayload); return sdp; } // Append stereo=1 to fmtp line. sdpLines[fmtpLineIndex] = sdpLines[fmtpLineIndex].concat(' stereo=1'); sdp = sdpLines.join('\r\n'); console.log("Enabled opus stereo."); return sdp; }; Utils.prototype.preferOpus = function(sdp) { // Set Opus as the preferred codec in SDP if Opus is present. var sdpLines = sdp.split('\r\n'); var mLineIndex = null; var i; // Search for m line. for (i=0; i < sdpLines.length; i++) { if (sdpLines[i].search('m=audio') !== -1) { mLineIndex = i; break; } } if (mLineIndex === null) { return sdp; } // If Opus is available, set it as the default in m line. for (i=0; i < sdpLines.length; i++) { if (sdpLines[i].search('opus/48000') !== -1) { var opusPayload = this.extractSdp(sdpLines[i], /:(\d+) opus\/48000/i); if (opusPayload) { sdpLines[mLineIndex] = this.setDefaultCodec(sdpLines[mLineIndex], opusPayload); } break; } } // Remove CN in m line and sdp. sdpLines = this.removeCN(sdpLines, mLineIndex); sdp = sdpLines.join('\r\n'); return sdp; }; Utils.prototype.setDefaultCodec = function (mLine, payload) { // Set the selected codec to the first in m line. var elements = mLine.split(' '); var newLine = []; var index = 0; for (var i = 0; i < elements.length; i++) { // Format of media starts from the fourth. if (index === 3) { newLine[index++] = payload; // Put target payload to the first. } if (elements[i] !== payload) { newLine[index++] = elements[i]; } } return newLine.join(' '); }; Utils.prototype.removeCN = function(sdpLines, mLineIndex) { // Strip CN from sdp before CN constraints is ready. var mLineElements = sdpLines[mLineIndex].split(' '); // Scan from end for the convenience of removing an item. for (var i = sdpLines.length-1; i >= 0; i--) { var payload = this.extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i); if (payload) { var cnPos = mLineElements.indexOf(payload); if (cnPos !== -1) { // Remove CN payload from m line. mLineElements.splice(cnPos, 1); } // Remove CN line in sdp sdpLines.splice(i, 1); } } sdpLines[mLineIndex] = mLineElements.join(' '); return sdpLines; }; var utils = new Utils(); return utils; });