154 lines
4.2 KiB
JavaScript
154 lines
4.2 KiB
JavaScript
//Get the Medooze Media Server interface
|
|
const MediaServer = require("medooze-media-server");
|
|
|
|
//Get Semantic SDP objects
|
|
const SemanticSDP = require("semantic-sdp");
|
|
const SDPInfo = SemanticSDP.SDPInfo;
|
|
const MediaInfo = SemanticSDP.MediaInfo;
|
|
const CandidateInfo = SemanticSDP.CandidateInfo;
|
|
const DTLSInfo = SemanticSDP.DTLSInfo;
|
|
const ICEInfo = SemanticSDP.ICEInfo;
|
|
const StreamInfo = SemanticSDP.StreamInfo;
|
|
const TrackInfo = SemanticSDP.TrackInfo;
|
|
const Direction = SemanticSDP.Direction;
|
|
const CodecInfo = SemanticSDP.CodecInfo;
|
|
|
|
const Capabilities = {
|
|
video : {
|
|
codecs : ["vp9"],
|
|
rtx : true,
|
|
rtcpfbs : [
|
|
{ "id": "transport-cc"},
|
|
{ "id": "ccm", "params": ["fir"]},
|
|
{ "id": "nack"},
|
|
{ "id": "nack", "params": ["pli"]}
|
|
],
|
|
extensions : [ "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"]
|
|
}
|
|
};
|
|
|
|
module.exports = function(request,protocol,endpoint)
|
|
{
|
|
const connection = request.accept(protocol);
|
|
|
|
connection.on('message', (frame) =>
|
|
{
|
|
//Get cmd
|
|
var msg = JSON.parse(frame.utf8Data);
|
|
|
|
//Get cmd
|
|
if (msg.cmd==="OFFER")
|
|
{
|
|
const streams = {};
|
|
|
|
//Process the sdp
|
|
var offer = SDPInfo.process(msg.offer);
|
|
|
|
//Create an DTLS ICE transport in that enpoint
|
|
const transport = endpoint.createTransport(offer);
|
|
|
|
//Enable probing
|
|
transport.setBandwidthProbing(true);
|
|
transport.setMaxProbingBitrate(512000);
|
|
|
|
//DUMP
|
|
//transport.dump("recordings/svc-"+ts+".pcap",{incoming:true,rtcp:true,rtpHeadersOnly:true,bwe:true});
|
|
|
|
//Set RTP remote properties
|
|
transport.setRemoteProperties({
|
|
audio : offer.getMedia("audio"),
|
|
video : offer.getMedia("video")
|
|
});
|
|
|
|
//Create local SDP info
|
|
const answer = offer.answer({
|
|
dtls : transport.getLocalDTLSInfo(),
|
|
ice : transport.getLocalICEInfo(),
|
|
candidates : endpoint.getLocalCandidates(),
|
|
capabilities : Capabilities
|
|
});
|
|
|
|
//Set RTP local properties
|
|
transport.setLocalProperties({
|
|
video : answer.getMedia("video")
|
|
});
|
|
|
|
//Get offered stream info
|
|
const offered = offer.getFirstStream();
|
|
|
|
//Create the remote stream into the transports
|
|
const incomingStream = transport.createIncomingStream(offered);
|
|
|
|
//Create new local stream
|
|
const outgoingStream = transport.createOutgoingStream({
|
|
audio: false,
|
|
video: true
|
|
});
|
|
|
|
//Get local stream info
|
|
const info = outgoingStream.getStreamInfo();
|
|
|
|
//Copy incoming data from the remote stream to the local one
|
|
const transponder = connection.transporder = outgoingStream.attachTo(incomingStream)[0];
|
|
|
|
//Start on low
|
|
transponder.selectLayer(0,0);
|
|
|
|
//Listen for bwe events
|
|
transport.on("targetbitrate", bitrate=>{
|
|
//Get previous layer ids
|
|
const sid = transponder.getSelectedSpatialLayerId();
|
|
const tid = transponder.getSelectedTemporalLayerId();
|
|
//Select stream layer from bitrate
|
|
const rate = transponder.setTargetBitrate(bitrate);
|
|
//Get next layer
|
|
const next = rate.layers[rate.layerIndex-1];
|
|
//Probing
|
|
let probing = false;
|
|
//If the jump is lower
|
|
if (next)
|
|
{
|
|
//Set probing bitrate
|
|
probing = next.bitrate-rate;
|
|
//Set it on transport
|
|
transport.setMaxProbingBitrate(next.bitrate-rate);
|
|
//Enable
|
|
transport.setBandwidthProbing(true);
|
|
} else
|
|
//Disable
|
|
transport.setBandwidthProbing(false);
|
|
|
|
//Log
|
|
console.log("targetbitrate :" + bitrate + " probing:" + probing +" sid:" + transponder.getSelectedSpatialLayerId() + " tid:" +transponder.getSelectedTemporalLayerId());
|
|
//If changed
|
|
if (sid!=transponder.getSelectedSpatialLayerId() || tid!=transponder.getSelectedTemporalLayerId())
|
|
//Send response
|
|
connection.sendUTF(JSON.stringify({
|
|
sid : transponder.getSelectedSpatialLayerId(),
|
|
tid : transponder.getSelectedTemporalLayerId()
|
|
}));
|
|
});
|
|
|
|
//Add local stream info it to the answer
|
|
answer.addStream(info);
|
|
|
|
//Add to streams
|
|
streams[incomingStream.getId()] = incomingStream;
|
|
|
|
//Send response
|
|
connection.sendUTF(JSON.stringify({
|
|
answer : answer.toString()
|
|
}));
|
|
|
|
//Close on disconnect
|
|
connection.on("close",() => {
|
|
//Stop
|
|
transport.stop();
|
|
});
|
|
} else {
|
|
//Select layer
|
|
connection.transporder.selectLayer(parseInt(msg.spatialLayerId),parseInt(msg.temporalLayerId));
|
|
}
|
|
});
|
|
};
|