Skip to content

Commit 805776b

Browse files
committed
Initial commit
0 parents  commit 805776b

12 files changed

+4509
-0
lines changed

genCommitId.sh

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
commitId=$(git rev-parse --short=10 HEAD)
3+
if [ "$?" != "0" ]; then
4+
commitId="<unknown>"
5+
fi
6+
7+
if [ -e "./shared/commitId.ts" ]; then
8+
curr=`sed -rn 's/.*COMMIT_ID\s*=\s*\x27(.+)\x27.*/\1/p' ./shared/commitId.ts`
9+
if [ "$curr" == "$commitId" ]; then
10+
# echo "commitId.ts is up to date"
11+
exit 0
12+
fi
13+
fi
14+
echo "Generating commitId.ts with commit hash '$commitId'"
15+
echo -e "const COMMIT_ID = '$commitId';\nexport default COMMIT_ID;" > ./shared/commitId.ts

shared/av.ts

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export default class Av {
2+
static Audio = 1;
3+
static CameraLowRes = 2; static CameraHiRes = 4; static Camera = 6;
4+
static ScreenLowRes = 8; static ScreenHiRes = 16; static Screen = 24;
5+
static LowResVideo = 10; static HiResVideo = 20; static Video = 30;
6+
static onHold = 128;
7+
static hasCamAndScreen(av: number) {
8+
return ((av & Av.Camera) && (av & Av.Screen));
9+
}
10+
static toString(av: number) {
11+
let result = (av & Av.onHold) ? "H" : "";
12+
if (av & Av.Audio) {
13+
result += "a";
14+
}
15+
if (av & Av.CameraHiRes) {
16+
result += "C";
17+
}
18+
if (av & Av.CameraLowRes) {
19+
result += "c";
20+
}
21+
if (av & Av.ScreenHiRes) {
22+
result += "S";
23+
}
24+
if (av & Av.ScreenLowRes) {
25+
result += "s";
26+
}
27+
return result;
28+
}
29+
}

shared/sdpCompress.ts

+291
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
const endl = "\r\n";
2+
class Ssrc {
3+
id: number;
4+
cname?: string;
5+
constructor(id: number) {
6+
this.id = id;
7+
}
8+
}
9+
class Track {
10+
t: string;
11+
sdp?: string;
12+
mid?: number;
13+
id?: string;
14+
sid?: string;
15+
dir?: string;
16+
ssrcs?: Ssrc[];
17+
ssrcg?: string[];
18+
constructor(type: string) {
19+
this.t = type;
20+
}
21+
static uncompress(track: Track, template: string) {
22+
let sdp = template;
23+
if (track.sdp) {
24+
sdp += track.sdp + "\r\n";
25+
}
26+
sdp += "a=mid:" + track.mid + endl;
27+
sdp += "a=" + track.dir + endl;
28+
if (track.id) { // recvonly tracks don't have it
29+
sdp += "a=msid:" + track.sid + " " + track.id + endl;
30+
}
31+
if (track.ssrcs) {
32+
for (let ssrc of track.ssrcs) {
33+
let id = ssrc.id;
34+
sdp += "a=ssrc:" + id + " cname:" + (ssrc.cname ? ssrc.cname : track.sid) + endl;
35+
sdp += "a=ssrc:" + id + " msid:" + track.sid + " " + track.id + endl;
36+
// sdp += "a=ssrc:" + id + " mslabel:" + track.sid + endl;
37+
// sdp += "a=ssrc:" + id + " label:" + track.id + endl;
38+
}
39+
if (track.ssrcg) {
40+
for (let grp of track.ssrcg) {
41+
sdp += "a=ssrc-group:" + grp + endl;
42+
}
43+
}
44+
}
45+
return sdp;
46+
}
47+
48+
}
49+
class CompressedSdp {
50+
data: Record<string, any>;
51+
constructor(sdp: any) {
52+
if (sdp instanceof Object) {
53+
this.data = sdp;
54+
return;
55+
}
56+
let data = this.data = {
57+
cmn: "",
58+
atpl: "",
59+
vtpl: "",
60+
tracks: []
61+
};
62+
63+
let lines = sdp.split(/\r\n/);
64+
let i = 0;
65+
for (; i < lines.length; i++) {
66+
let line = lines[i];
67+
if (line.substr(0, 2) === "m=") {
68+
break;
69+
}
70+
data.cmn += line + endl;
71+
}
72+
while (i < lines.length) {
73+
let line = lines[i];
74+
let type = line.substr(2, 5);
75+
if (type === "audio" && !data.atpl) {
76+
i = this._createTemplate("atpl", lines, i);
77+
if (data.vtpl) {
78+
break;
79+
}
80+
} else if (type === "video" && !data.vtpl) {
81+
i = this._createTemplate("vtpl", lines, i);
82+
if (data.atpl) {
83+
break;
84+
}
85+
} else {
86+
i = nextMline(lines, i + 1);
87+
}
88+
}
89+
for (i = nextMline(lines, 0); i < lines.length;) {
90+
i = this._addTrack(lines, i);
91+
}
92+
}
93+
protected _createTemplate(tname: string, lines: string[], i: number) {
94+
let template = lines[i++] + endl;
95+
for (; i < lines.length; i++) {
96+
let line = lines[i];
97+
let ltype = line.charAt(0);
98+
if (ltype === 'm') {
99+
break;
100+
}
101+
if (ltype !== 'a') {
102+
template += line + endl;
103+
continue;
104+
}
105+
let name = nextWord(line, 2)[0];
106+
if (name === "recvonly") { // we don't want to make a template from a recvonly description
107+
// consume lines till next m-line
108+
return nextMline(lines, i);
109+
}
110+
switch(name) {
111+
case "sendrecv":
112+
case "sendonly":
113+
case "ssrc-group":
114+
case "ssrc":
115+
case "mid":
116+
case "msid":
117+
continue;
118+
default:
119+
template += line + endl;
120+
}
121+
}
122+
this.data[tname] = template;
123+
return i;
124+
}
125+
126+
_addTrack(lines: string[], i: number) {
127+
let type = lines[i++].substr(2, 5);
128+
if (type === "audio") {
129+
type = "a";
130+
} else if (type === "video") {
131+
type = "v"
132+
};
133+
let track = new Track(type);
134+
let ssrcIds = new Set;
135+
for (; i < lines.length; i++) {
136+
let line = lines[i];
137+
let ltype = line.charAt(0);
138+
if (ltype === 'm') {
139+
break;
140+
}
141+
if (ltype !== 'a') {
142+
continue;
143+
}
144+
let name = nextWord(line, 2)[0];
145+
switch (name) {
146+
case "sendrecv":
147+
case "recvonly":
148+
case "sendonly": {
149+
track.dir = name;
150+
break;
151+
}
152+
case "mid": {
153+
track.mid = parseInt(line.substr(6));
154+
break;
155+
}
156+
case "msid": {
157+
let parts = line.substr(7).split(' ');
158+
track.sid = parts[0];
159+
track.id = parts[1];
160+
break;
161+
}
162+
case "ssrc-group": {
163+
if (!track.ssrcg) {
164+
track.ssrcg = [];
165+
}
166+
track.ssrcg.push(line.substr(13));
167+
break;
168+
}
169+
case "ssrc": {
170+
let ret = nextWord(line, 7);
171+
let id = parseInt(ret[0]);
172+
if (ssrcIds.has(id)) {
173+
break;
174+
}
175+
ssrcIds.add(id);
176+
ret = nextWord(line, ret[1] + 1);
177+
let cname = nextWord(line, ret[1] + 1)[0];
178+
let ssrc = new Ssrc(id);
179+
if (cname !== track.sid) {
180+
ssrc.cname = cname;
181+
}
182+
if (!track.ssrcs) {
183+
track.ssrcs = [ssrc];
184+
} else {
185+
track.ssrcs.push(ssrc);
186+
}
187+
break;
188+
}
189+
}
190+
}
191+
this.data.tracks.push(track);
192+
return i;
193+
}
194+
uncompress() {
195+
let sdp = this.data.cmn;
196+
for (let track of this.data.tracks) {
197+
if (track.t === "a") {
198+
sdp += Track.uncompress(track, this.data.atpl);
199+
} else if (track.t === "v") {
200+
sdp += Track.uncompress(track, this.data.vtpl);
201+
}
202+
}
203+
return sdp;
204+
}
205+
}
206+
207+
function nextWord(line: string, start: number): [string, number] {
208+
let i;
209+
for (i = start; i < line.length; i++) {
210+
let ch = line.charCodeAt(i);
211+
if ((ch >= 97 && ch <= 122) || // a - z
212+
(ch >= 65 && ch <= 90) || // A - Z
213+
(ch >= 48 && ch <= 57) || // 0 - 9
214+
(ch === 45) || (ch === 43) || (ch === 47) || (ch === 95)) { // - + /
215+
continue;
216+
}
217+
break;
218+
}
219+
return [line.substr(start, i - start), i];
220+
}
221+
222+
function nextMline(lines: string[], i: number) {
223+
for(; i < lines.length; i++) {
224+
if (lines[i].charAt(0) === "m") {
225+
return i;
226+
}
227+
}
228+
return i;
229+
}
230+
231+
export function sdpCompress(sdp: string) {
232+
/*
233+
console.log("original:\n", sdp);
234+
let csdp = (new CompressedSdp(sdp)).uncompress();
235+
console.log("compressed:\n", csdp);
236+
*/
237+
// return sdp;
238+
return (new CompressedSdp(sdp)).data;
239+
}
240+
export function sdpUncompress(sdp: any) {
241+
// return sdp;
242+
return (new CompressedSdp(sdp)).uncompress();
243+
}
244+
245+
function trackSummary(tracks: any) {
246+
let summary = "";
247+
if (tracks.tx) {
248+
summary += tracks.tx + " send";
249+
} else {
250+
summary += tracks.rx + " recv";
251+
}
252+
if (tracks.txrx) {
253+
summary += ", " + tracks.txrx + " sendrecv";
254+
}
255+
return summary;
256+
}
257+
export function compressedSdpToString(sdp: any) {
258+
let video = {rx: 0, tx: 0, txrx: 0, svc: 0};
259+
let audio = {rx: 0, tx: 0, txrx: 0};
260+
for (let track of sdp.tracks) {
261+
let type = track.t;
262+
let dir = track.dir;
263+
let info;
264+
if (type === "v") {
265+
info = video;
266+
if (track.ssrcg) {
267+
for (let ssrcg of track.ssrcg) {
268+
if (ssrcg.substr(0, 3) === "SIM") {
269+
video.svc++;
270+
}
271+
}
272+
}
273+
} else {
274+
info = audio;
275+
}
276+
if (dir === "recvonly") {
277+
info.rx++;
278+
} else if (dir === "sendrecv") {
279+
info.txrx++;
280+
} else if (dir === "sendonly") {
281+
info.tx++;
282+
}
283+
}
284+
let summary = "<vtracks: " + trackSummary(video);
285+
if (video.svc) {
286+
summary += ", " + video.svc + " SVC";
287+
}
288+
summary += "; atracks: " + trackSummary(audio) + ">";
289+
return summary;
290+
}
291+

shared/termCodes.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export enum TermCode {
2+
kFlagError = 128,
3+
kFlagDisconn = 64,
4+
kUserHangup = 0,
5+
kTooManyParticipants = 1,
6+
kLeavingRoom = 2,
7+
//====
8+
kRtcDisconn = kFlagDisconn | 0,
9+
kSigDisconn = kFlagDisconn | 1,
10+
kSfuShuttingDown = kFlagDisconn | 2,
11+
kChatDisconn = kFlagDisconn | 3,
12+
kNoMediaPath = kFlagDisconn | 4,
13+
//====
14+
kErrSignaling = kFlagError | 0,
15+
kErrNoCall = kFlagError | 1,
16+
kErrAuth = kFlagError | 2,
17+
kErrApiTimeout = kFlagError | 3,
18+
kErrSdp = kFlagError | 4,
19+
kErrClientGeneral = kFlagError | 62,
20+
kErrSfuGeneral = kFlagError | 63
21+
};
22+
export default TermCode;

0 commit comments

Comments
 (0)