-
Notifications
You must be signed in to change notification settings - Fork 49
/
simulcast.js
142 lines (113 loc) · 3.73 KB
/
simulcast.js
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
//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;
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")
{
//Process the sdp
var offer = SDPInfo.process(msg.offer);
//Create an DTLS ICE transport in that enpoint
const transport = endpoint.createTransport(offer);
//Set RTP remote properties
transport.setRemoteProperties(offer);
//Get local DTLS and ICE info
const dtls = transport.getLocalDTLSInfo();
const ice = transport.getLocalICEInfo();
//Get local candidates
const candidates = endpoint.getLocalCandidates();
//Create local SDP info
let answer = new SDPInfo();
//Add ice and dtls info
answer.setDTLS(dtls);
answer.setICE(ice);
//For each local candidate
for (let i=0;i<candidates.length;++i)
//Add candidate to media info
answer.addCandidate(candidates[i]);
//Get remote video m-line info
let videoOffer = offer.getMedia("video");
//If offer had video
if (videoOffer)
{
//Create video answer
const video = videoOffer.answer({
codecs: CodecInfo.MapFromNames(["VP8"], true),
extensions: new Set([
"urn:ietf:params:rtp-hdrext:toffset",
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
//"urn:3gpp:video-orientation",
"http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
"http://www.webrtc.org/experiments/rtp-hdrext/playout-delay",
"urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id",
"urn:ietf:params:rtp-hdrext:sdes:repair-rtp-stream-id",
"urn:ietf:params:rtp-hdrext:sdes:mid",
]),
simulcast: true
});
//Limit incoming bitrate
video.setBitrate(4096);
//Add it to answer
answer.addMedia(video);
}
//Set RTP local properties
transport.setLocalProperties({
video : answer.getMedia("video")
});
const ts = Date.now();
//Dump contents
//transport.dump("/tmp/"+ts+".pcap");
//Create recoreder
const recorder = MediaServer.createRecorder ("/tmp/"+ts +".mp4");
//For each stream offered
for (let offered of offer.getStreams().values())
{
//Create the remote stream into the transport
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
connection.transporder = outgoingStream.attachTo(incomingStream)[0];
//Add local stream info it to the answer
answer.addStream(info);
//Record it
recorder.record(incomingStream);
}
//Send response
connection.sendUTF(JSON.stringify({
answer : answer.toString()
}));
//Close on disconnect
connection.on("close",() => {
//Stop transport an recorded
transport.stop();
recorder.stop();
});
} else {
connection.transporder.selectEncoding(msg.rid);
//Select layer
connection.transporder.selectLayer(parseInt(msg.spatialLayerId),parseInt(msg.temporalLayerId));
}
});
};