@webex/internal-media-core 0.0.4-beta → 0.0.5-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +13246 -0
- package/dist/esm/index.js +1342 -762
- package/dist/types/Media/Effects/BNR/Bnr.d.ts.map +1 -1
- package/dist/types/Media/Effects/BNR/BnrMock.d.ts.map +1 -1
- package/dist/types/MediaConnection/MediaConnection.d.ts.map +1 -1
- package/dist/types/MediaConnection/config.d.ts +11 -0
- package/dist/types/MediaConnection/config.d.ts.map +1 -1
- package/dist/types/MediaConnection/logger.d.ts +1 -1
- package/dist/types/MediaConnection/logger.d.ts.map +1 -1
- package/dist/types/MediaConnection/utils.d.ts +3 -0
- package/dist/types/MediaConnection/utils.d.ts.map +1 -1
- package/dist/types/MediaConnection/utils.test-fixtures.d.ts +10 -0
- package/dist/types/MediaConnection/utils.test-fixtures.d.ts.map +1 -1
- package/package.json +11 -7
- package/dist/types/MediaConnection/MediaConnection.integration-test.d.ts +0 -2
- package/dist/types/MediaConnection/MediaConnection.integration-test.d.ts.map +0 -1
- package/dist/types/MediaConnection/testUtils.d.ts +0 -7
- package/dist/types/MediaConnection/testUtils.d.ts.map +0 -1
package/dist/esm/index.js
CHANGED
|
@@ -2473,762 +2473,1204 @@ const getErrorDescription = (error) => {
|
|
|
2473
2473
|
return error ? (error.stack ? `${error.message}: ${error.stack}` : `${error}`) : '';
|
|
2474
2474
|
};
|
|
2475
2475
|
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
var grammar$2 = {exports: {}};
|
|
2481
|
-
|
|
2482
|
-
var grammar$1 = grammar$2.exports = {
|
|
2483
|
-
v: [{
|
|
2484
|
-
name: 'version',
|
|
2485
|
-
reg: /^(\d*)$/
|
|
2486
|
-
}],
|
|
2487
|
-
o: [{
|
|
2488
|
-
// o=- 20518 0 IN IP4 203.0.113.1
|
|
2489
|
-
// NB: sessionId will be a String in most cases because it is huge
|
|
2490
|
-
name: 'origin',
|
|
2491
|
-
reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/,
|
|
2492
|
-
names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],
|
|
2493
|
-
format: '%s %s %d %s IP%d %s'
|
|
2494
|
-
}],
|
|
2495
|
-
// default parsing of these only (though some of these feel outdated)
|
|
2496
|
-
s: [{ name: 'name' }],
|
|
2497
|
-
i: [{ name: 'description' }],
|
|
2498
|
-
u: [{ name: 'uri' }],
|
|
2499
|
-
e: [{ name: 'email' }],
|
|
2500
|
-
p: [{ name: 'phone' }],
|
|
2501
|
-
z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly...
|
|
2502
|
-
r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly
|
|
2503
|
-
// k: [{}], // outdated thing ignored
|
|
2504
|
-
t: [{
|
|
2505
|
-
// t=0 0
|
|
2506
|
-
name: 'timing',
|
|
2507
|
-
reg: /^(\d*) (\d*)/,
|
|
2508
|
-
names: ['start', 'stop'],
|
|
2509
|
-
format: '%d %d'
|
|
2510
|
-
}],
|
|
2511
|
-
c: [{
|
|
2512
|
-
// c=IN IP4 10.47.197.26
|
|
2513
|
-
name: 'connection',
|
|
2514
|
-
reg: /^IN IP(\d) (\S*)/,
|
|
2515
|
-
names: ['version', 'ip'],
|
|
2516
|
-
format: 'IN IP%d %s'
|
|
2517
|
-
}],
|
|
2518
|
-
b: [{
|
|
2519
|
-
// b=AS:4000
|
|
2520
|
-
push: 'bandwidth',
|
|
2521
|
-
reg: /^(TIAS|AS|CT|RR|RS):(\d*)/,
|
|
2522
|
-
names: ['type', 'limit'],
|
|
2523
|
-
format: '%s:%s'
|
|
2524
|
-
}],
|
|
2525
|
-
m: [{
|
|
2526
|
-
// m=video 51744 RTP/AVP 126 97 98 34 31
|
|
2527
|
-
// NB: special - pushes to session
|
|
2528
|
-
// TODO: rtp/fmtp should be filtered by the payloads found here?
|
|
2529
|
-
reg: /^(\w*) (\d*) ([\w/]*)(?: (.*))?/,
|
|
2530
|
-
names: ['type', 'port', 'protocol', 'payloads'],
|
|
2531
|
-
format: '%s %d %s %s'
|
|
2532
|
-
}],
|
|
2533
|
-
a: [
|
|
2534
|
-
{
|
|
2535
|
-
// a=rtpmap:110 opus/48000/2
|
|
2536
|
-
push: 'rtp',
|
|
2537
|
-
reg: /^rtpmap:(\d*) ([\w\-.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/,
|
|
2538
|
-
names: ['payload', 'codec', 'rate', 'encoding'],
|
|
2539
|
-
format: function (o) {
|
|
2540
|
-
return (o.encoding)
|
|
2541
|
-
? 'rtpmap:%d %s/%s/%s'
|
|
2542
|
-
: o.rate
|
|
2543
|
-
? 'rtpmap:%d %s/%s'
|
|
2544
|
-
: 'rtpmap:%d %s';
|
|
2545
|
-
}
|
|
2546
|
-
},
|
|
2547
|
-
{
|
|
2548
|
-
// a=fmtp:108 profile-level-id=24;object=23;bitrate=64000
|
|
2549
|
-
// a=fmtp:111 minptime=10; useinbandfec=1
|
|
2550
|
-
push: 'fmtp',
|
|
2551
|
-
reg: /^fmtp:(\d*) ([\S| ]*)/,
|
|
2552
|
-
names: ['payload', 'config'],
|
|
2553
|
-
format: 'fmtp:%d %s'
|
|
2554
|
-
},
|
|
2555
|
-
{
|
|
2556
|
-
// a=control:streamid=0
|
|
2557
|
-
name: 'control',
|
|
2558
|
-
reg: /^control:(.*)/,
|
|
2559
|
-
format: 'control:%s'
|
|
2560
|
-
},
|
|
2561
|
-
{
|
|
2562
|
-
// a=rtcp:65179 IN IP4 193.84.77.194
|
|
2563
|
-
name: 'rtcp',
|
|
2564
|
-
reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/,
|
|
2565
|
-
names: ['port', 'netType', 'ipVer', 'address'],
|
|
2566
|
-
format: function (o) {
|
|
2567
|
-
return (o.address != null)
|
|
2568
|
-
? 'rtcp:%d %s IP%d %s'
|
|
2569
|
-
: 'rtcp:%d';
|
|
2570
|
-
}
|
|
2571
|
-
},
|
|
2572
|
-
{
|
|
2573
|
-
// a=rtcp-fb:98 trr-int 100
|
|
2574
|
-
push: 'rtcpFbTrrInt',
|
|
2575
|
-
reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/,
|
|
2576
|
-
names: ['payload', 'value'],
|
|
2577
|
-
format: 'rtcp-fb:%s trr-int %d'
|
|
2578
|
-
},
|
|
2579
|
-
{
|
|
2580
|
-
// a=rtcp-fb:98 nack rpsi
|
|
2581
|
-
push: 'rtcpFb',
|
|
2582
|
-
reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/,
|
|
2583
|
-
names: ['payload', 'type', 'subtype'],
|
|
2584
|
-
format: function (o) {
|
|
2585
|
-
return (o.subtype != null)
|
|
2586
|
-
? 'rtcp-fb:%s %s %s'
|
|
2587
|
-
: 'rtcp-fb:%s %s';
|
|
2588
|
-
}
|
|
2589
|
-
},
|
|
2590
|
-
{
|
|
2591
|
-
// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
|
|
2592
|
-
// a=extmap:1/recvonly URI-gps-string
|
|
2593
|
-
// a=extmap:3 urn:ietf:params:rtp-hdrext:encrypt urn:ietf:params:rtp-hdrext:smpte-tc 25@600/24
|
|
2594
|
-
push: 'ext',
|
|
2595
|
-
reg: /^extmap:(\d+)(?:\/(\w+))?(?: (urn:ietf:params:rtp-hdrext:encrypt))? (\S*)(?: (\S*))?/,
|
|
2596
|
-
names: ['value', 'direction', 'encrypt-uri', 'uri', 'config'],
|
|
2597
|
-
format: function (o) {
|
|
2598
|
-
return (
|
|
2599
|
-
'extmap:%d' +
|
|
2600
|
-
(o.direction ? '/%s' : '%v') +
|
|
2601
|
-
(o['encrypt-uri'] ? ' %s' : '%v') +
|
|
2602
|
-
' %s' +
|
|
2603
|
-
(o.config ? ' %s' : '')
|
|
2604
|
-
);
|
|
2605
|
-
}
|
|
2606
|
-
},
|
|
2607
|
-
{
|
|
2608
|
-
// a=extmap-allow-mixed
|
|
2609
|
-
name: 'extmapAllowMixed',
|
|
2610
|
-
reg: /^(extmap-allow-mixed)/
|
|
2611
|
-
},
|
|
2612
|
-
{
|
|
2613
|
-
// a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32
|
|
2614
|
-
push: 'crypto',
|
|
2615
|
-
reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/,
|
|
2616
|
-
names: ['id', 'suite', 'config', 'sessionConfig'],
|
|
2617
|
-
format: function (o) {
|
|
2618
|
-
return (o.sessionConfig != null)
|
|
2619
|
-
? 'crypto:%d %s %s %s'
|
|
2620
|
-
: 'crypto:%d %s %s';
|
|
2621
|
-
}
|
|
2622
|
-
},
|
|
2623
|
-
{
|
|
2624
|
-
// a=setup:actpass
|
|
2625
|
-
name: 'setup',
|
|
2626
|
-
reg: /^setup:(\w*)/,
|
|
2627
|
-
format: 'setup:%s'
|
|
2628
|
-
},
|
|
2629
|
-
{
|
|
2630
|
-
// a=connection:new
|
|
2631
|
-
name: 'connectionType',
|
|
2632
|
-
reg: /^connection:(new|existing)/,
|
|
2633
|
-
format: 'connection:%s'
|
|
2634
|
-
},
|
|
2635
|
-
{
|
|
2636
|
-
// a=mid:1
|
|
2637
|
-
name: 'mid',
|
|
2638
|
-
reg: /^mid:([^\s]*)/,
|
|
2639
|
-
format: 'mid:%s'
|
|
2640
|
-
},
|
|
2641
|
-
{
|
|
2642
|
-
// a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a
|
|
2643
|
-
name: 'msid',
|
|
2644
|
-
reg: /^msid:(.*)/,
|
|
2645
|
-
format: 'msid:%s'
|
|
2646
|
-
},
|
|
2647
|
-
{
|
|
2648
|
-
// a=ptime:20
|
|
2649
|
-
name: 'ptime',
|
|
2650
|
-
reg: /^ptime:(\d*(?:\.\d*)*)/,
|
|
2651
|
-
format: 'ptime:%d'
|
|
2652
|
-
},
|
|
2653
|
-
{
|
|
2654
|
-
// a=maxptime:60
|
|
2655
|
-
name: 'maxptime',
|
|
2656
|
-
reg: /^maxptime:(\d*(?:\.\d*)*)/,
|
|
2657
|
-
format: 'maxptime:%d'
|
|
2658
|
-
},
|
|
2659
|
-
{
|
|
2660
|
-
// a=sendrecv
|
|
2661
|
-
name: 'direction',
|
|
2662
|
-
reg: /^(sendrecv|recvonly|sendonly|inactive)/
|
|
2663
|
-
},
|
|
2664
|
-
{
|
|
2665
|
-
// a=ice-lite
|
|
2666
|
-
name: 'icelite',
|
|
2667
|
-
reg: /^(ice-lite)/
|
|
2668
|
-
},
|
|
2669
|
-
{
|
|
2670
|
-
// a=ice-ufrag:F7gI
|
|
2671
|
-
name: 'iceUfrag',
|
|
2672
|
-
reg: /^ice-ufrag:(\S*)/,
|
|
2673
|
-
format: 'ice-ufrag:%s'
|
|
2674
|
-
},
|
|
2675
|
-
{
|
|
2676
|
-
// a=ice-pwd:x9cml/YzichV2+XlhiMu8g
|
|
2677
|
-
name: 'icePwd',
|
|
2678
|
-
reg: /^ice-pwd:(\S*)/,
|
|
2679
|
-
format: 'ice-pwd:%s'
|
|
2680
|
-
},
|
|
2681
|
-
{
|
|
2682
|
-
// a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33
|
|
2683
|
-
name: 'fingerprint',
|
|
2684
|
-
reg: /^fingerprint:(\S*) (\S*)/,
|
|
2685
|
-
names: ['type', 'hash'],
|
|
2686
|
-
format: 'fingerprint:%s %s'
|
|
2687
|
-
},
|
|
2688
|
-
{
|
|
2689
|
-
// a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
|
|
2690
|
-
// a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 network-id 3 network-cost 10
|
|
2691
|
-
// a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10
|
|
2692
|
-
// a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10
|
|
2693
|
-
// a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10
|
|
2694
|
-
push:'candidates',
|
|
2695
|
-
reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/,
|
|
2696
|
-
names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'],
|
|
2697
|
-
format: function (o) {
|
|
2698
|
-
var str = 'candidate:%s %d %s %d %s %d typ %s';
|
|
2476
|
+
const NUM = '\\d+';
|
|
2477
|
+
const TOKEN = '\\S+';
|
|
2478
|
+
const SP = '\\s';
|
|
2479
|
+
const REST = '.+';
|
|
2699
2480
|
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
// NB: candidate has three optional chunks, so %void middles one if it's missing
|
|
2703
|
-
str += (o.tcptype != null) ? ' tcptype %s' : '%v';
|
|
2704
|
-
|
|
2705
|
-
if (o.generation != null) {
|
|
2706
|
-
str += ' generation %d';
|
|
2707
|
-
}
|
|
2708
|
-
|
|
2709
|
-
str += (o['network-id'] != null) ? ' network-id %d' : '%v';
|
|
2710
|
-
str += (o['network-cost'] != null) ? ' network-cost %d' : '%v';
|
|
2711
|
-
return str;
|
|
2712
|
-
}
|
|
2713
|
-
},
|
|
2714
|
-
{
|
|
2715
|
-
// a=end-of-candidates (keep after the candidates line for readability)
|
|
2716
|
-
name: 'endOfCandidates',
|
|
2717
|
-
reg: /^(end-of-candidates)/
|
|
2718
|
-
},
|
|
2719
|
-
{
|
|
2720
|
-
// a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...
|
|
2721
|
-
name: 'remoteCandidates',
|
|
2722
|
-
reg: /^remote-candidates:(.*)/,
|
|
2723
|
-
format: 'remote-candidates:%s'
|
|
2724
|
-
},
|
|
2725
|
-
{
|
|
2726
|
-
// a=ice-options:google-ice
|
|
2727
|
-
name: 'iceOptions',
|
|
2728
|
-
reg: /^ice-options:(\S*)/,
|
|
2729
|
-
format: 'ice-options:%s'
|
|
2730
|
-
},
|
|
2731
|
-
{
|
|
2732
|
-
// a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1
|
|
2733
|
-
push: 'ssrcs',
|
|
2734
|
-
reg: /^ssrc:(\d*) ([\w_-]*)(?::(.*))?/,
|
|
2735
|
-
names: ['id', 'attribute', 'value'],
|
|
2736
|
-
format: function (o) {
|
|
2737
|
-
var str = 'ssrc:%d';
|
|
2738
|
-
if (o.attribute != null) {
|
|
2739
|
-
str += ' %s';
|
|
2740
|
-
if (o.value != null) {
|
|
2741
|
-
str += ':%s';
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
return str;
|
|
2745
|
-
}
|
|
2746
|
-
},
|
|
2747
|
-
{
|
|
2748
|
-
// a=ssrc-group:FEC 1 2
|
|
2749
|
-
// a=ssrc-group:FEC-FR 3004364195 1080772241
|
|
2750
|
-
push: 'ssrcGroups',
|
|
2751
|
-
// token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E
|
|
2752
|
-
reg: /^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/,
|
|
2753
|
-
names: ['semantics', 'ssrcs'],
|
|
2754
|
-
format: 'ssrc-group:%s %s'
|
|
2755
|
-
},
|
|
2756
|
-
{
|
|
2757
|
-
// a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV
|
|
2758
|
-
name: 'msidSemantic',
|
|
2759
|
-
reg: /^msid-semantic:\s?(\w*) (\S*)/,
|
|
2760
|
-
names: ['semantic', 'token'],
|
|
2761
|
-
format: 'msid-semantic: %s %s' // space after ':' is not accidental
|
|
2762
|
-
},
|
|
2763
|
-
{
|
|
2764
|
-
// a=group:BUNDLE audio video
|
|
2765
|
-
push: 'groups',
|
|
2766
|
-
reg: /^group:(\w*) (.*)/,
|
|
2767
|
-
names: ['type', 'mids'],
|
|
2768
|
-
format: 'group:%s %s'
|
|
2769
|
-
},
|
|
2770
|
-
{
|
|
2771
|
-
// a=rtcp-mux
|
|
2772
|
-
name: 'rtcpMux',
|
|
2773
|
-
reg: /^(rtcp-mux)/
|
|
2774
|
-
},
|
|
2775
|
-
{
|
|
2776
|
-
// a=rtcp-rsize
|
|
2777
|
-
name: 'rtcpRsize',
|
|
2778
|
-
reg: /^(rtcp-rsize)/
|
|
2779
|
-
},
|
|
2780
|
-
{
|
|
2781
|
-
// a=sctpmap:5000 webrtc-datachannel 1024
|
|
2782
|
-
name: 'sctpmap',
|
|
2783
|
-
reg: /^sctpmap:([\w_/]*) (\S*)(?: (\S*))?/,
|
|
2784
|
-
names: ['sctpmapNumber', 'app', 'maxMessageSize'],
|
|
2785
|
-
format: function (o) {
|
|
2786
|
-
return (o.maxMessageSize != null)
|
|
2787
|
-
? 'sctpmap:%s %s %s'
|
|
2788
|
-
: 'sctpmap:%s %s';
|
|
2789
|
-
}
|
|
2790
|
-
},
|
|
2791
|
-
{
|
|
2792
|
-
// a=x-google-flag:conference
|
|
2793
|
-
name: 'xGoogleFlag',
|
|
2794
|
-
reg: /^x-google-flag:([^\s]*)/,
|
|
2795
|
-
format: 'x-google-flag:%s'
|
|
2796
|
-
},
|
|
2797
|
-
{
|
|
2798
|
-
// a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0
|
|
2799
|
-
push: 'rids',
|
|
2800
|
-
reg: /^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/,
|
|
2801
|
-
names: ['id', 'direction', 'params'],
|
|
2802
|
-
format: function (o) {
|
|
2803
|
-
return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s';
|
|
2804
|
-
}
|
|
2805
|
-
},
|
|
2806
|
-
{
|
|
2807
|
-
// a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250]
|
|
2808
|
-
// a=imageattr:* send [x=800,y=640] recv *
|
|
2809
|
-
// a=imageattr:100 recv [x=320,y=240]
|
|
2810
|
-
push: 'imageattrs',
|
|
2811
|
-
reg: new RegExp(
|
|
2812
|
-
// a=imageattr:97
|
|
2813
|
-
'^imageattr:(\\d+|\\*)' +
|
|
2814
|
-
// send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320]
|
|
2815
|
-
'[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' +
|
|
2816
|
-
// recv [x=330,y=250]
|
|
2817
|
-
'(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?'
|
|
2818
|
-
),
|
|
2819
|
-
names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'],
|
|
2820
|
-
format: function (o) {
|
|
2821
|
-
return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : '');
|
|
2822
|
-
}
|
|
2823
|
-
},
|
|
2824
|
-
{
|
|
2825
|
-
// a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8
|
|
2826
|
-
// a=simulcast:recv 1;4,5 send 6;7
|
|
2827
|
-
name: 'simulcast',
|
|
2828
|
-
reg: new RegExp(
|
|
2829
|
-
// a=simulcast:
|
|
2830
|
-
'^simulcast:' +
|
|
2831
|
-
// send 1,2,3;~4,~5
|
|
2832
|
-
'(send|recv) ([a-zA-Z0-9\\-_~;,]+)' +
|
|
2833
|
-
// space + recv 6;~7,~8
|
|
2834
|
-
'(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' +
|
|
2835
|
-
// end
|
|
2836
|
-
'$'
|
|
2837
|
-
),
|
|
2838
|
-
names: ['dir1', 'list1', 'dir2', 'list2'],
|
|
2839
|
-
format: function (o) {
|
|
2840
|
-
return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : '');
|
|
2841
|
-
}
|
|
2842
|
-
},
|
|
2843
|
-
{
|
|
2844
|
-
// old simulcast draft 03 (implemented by Firefox)
|
|
2845
|
-
// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-simulcast-03
|
|
2846
|
-
// a=simulcast: recv pt=97;98 send pt=97
|
|
2847
|
-
// a=simulcast: send rid=5;6;7 paused=6,7
|
|
2848
|
-
name: 'simulcast_03',
|
|
2849
|
-
reg: /^simulcast:[\s\t]+([\S+\s\t]+)$/,
|
|
2850
|
-
names: ['value'],
|
|
2851
|
-
format: 'simulcast: %s'
|
|
2852
|
-
},
|
|
2853
|
-
{
|
|
2854
|
-
// a=framerate:25
|
|
2855
|
-
// a=framerate:29.97
|
|
2856
|
-
name: 'framerate',
|
|
2857
|
-
reg: /^framerate:(\d+(?:$|\.\d+))/,
|
|
2858
|
-
format: 'framerate:%s'
|
|
2859
|
-
},
|
|
2860
|
-
{
|
|
2861
|
-
// RFC4570
|
|
2862
|
-
// a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5
|
|
2863
|
-
name: 'sourceFilter',
|
|
2864
|
-
reg: /^source-filter: *(excl|incl) (\S*) (IP4|IP6|\*) (\S*) (.*)/,
|
|
2865
|
-
names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'],
|
|
2866
|
-
format: 'source-filter: %s %s %s %s %s'
|
|
2867
|
-
},
|
|
2868
|
-
{
|
|
2869
|
-
// a=bundle-only
|
|
2870
|
-
name: 'bundleOnly',
|
|
2871
|
-
reg: /^(bundle-only)/
|
|
2872
|
-
},
|
|
2873
|
-
{
|
|
2874
|
-
// a=label:1
|
|
2875
|
-
name: 'label',
|
|
2876
|
-
reg: /^label:(.+)/,
|
|
2877
|
-
format: 'label:%s'
|
|
2878
|
-
},
|
|
2879
|
-
{
|
|
2880
|
-
// RFC version 26 for SCTP over DTLS
|
|
2881
|
-
// https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5
|
|
2882
|
-
name: 'sctpPort',
|
|
2883
|
-
reg: /^sctp-port:(\d+)$/,
|
|
2884
|
-
format: 'sctp-port:%s'
|
|
2885
|
-
},
|
|
2886
|
-
{
|
|
2887
|
-
// RFC version 26 for SCTP over DTLS
|
|
2888
|
-
// https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6
|
|
2889
|
-
name: 'maxMessageSize',
|
|
2890
|
-
reg: /^max-message-size:(\d+)$/,
|
|
2891
|
-
format: 'max-message-size:%s'
|
|
2892
|
-
},
|
|
2893
|
-
{
|
|
2894
|
-
// RFC7273
|
|
2895
|
-
// a=ts-refclk:ptp=IEEE1588-2008:39-A7-94-FF-FE-07-CB-D0:37
|
|
2896
|
-
push:'tsRefClocks',
|
|
2897
|
-
reg: /^ts-refclk:([^\s=]*)(?:=(\S*))?/,
|
|
2898
|
-
names: ['clksrc', 'clksrcExt'],
|
|
2899
|
-
format: function (o) {
|
|
2900
|
-
return 'ts-refclk:%s' + (o.clksrcExt != null ? '=%s' : '');
|
|
2901
|
-
}
|
|
2902
|
-
},
|
|
2903
|
-
{
|
|
2904
|
-
// RFC7273
|
|
2905
|
-
// a=mediaclk:direct=963214424
|
|
2906
|
-
name:'mediaClk',
|
|
2907
|
-
reg: /^mediaclk:(?:id=(\S*))? *([^\s=]*)(?:=(\S*))?(?: *rate=(\d+)\/(\d+))?/,
|
|
2908
|
-
names: ['id', 'mediaClockName', 'mediaClockValue', 'rateNumerator', 'rateDenominator'],
|
|
2909
|
-
format: function (o) {
|
|
2910
|
-
var str = 'mediaclk:';
|
|
2911
|
-
str += (o.id != null ? 'id=%s %s' : '%v%s');
|
|
2912
|
-
str += (o.mediaClockValue != null ? '=%s' : '');
|
|
2913
|
-
str += (o.rateNumerator != null ? ' rate=%s' : '');
|
|
2914
|
-
str += (o.rateDenominator != null ? '/%s' : '');
|
|
2915
|
-
return str;
|
|
2916
|
-
}
|
|
2917
|
-
},
|
|
2918
|
-
{
|
|
2919
|
-
// a=keywds:keywords
|
|
2920
|
-
name: 'keywords',
|
|
2921
|
-
reg: /^keywds:(.+)$/,
|
|
2922
|
-
format: 'keywds:%s'
|
|
2923
|
-
},
|
|
2924
|
-
{
|
|
2925
|
-
// a=content:main
|
|
2926
|
-
name: 'content',
|
|
2927
|
-
reg: /^content:(.+)/,
|
|
2928
|
-
format: 'content:%s'
|
|
2929
|
-
},
|
|
2930
|
-
// BFCP https://tools.ietf.org/html/rfc4583
|
|
2931
|
-
{
|
|
2932
|
-
// a=floorctrl:c-s
|
|
2933
|
-
name: 'bfcpFloorCtrl',
|
|
2934
|
-
reg: /^floorctrl:(c-only|s-only|c-s)/,
|
|
2935
|
-
format: 'floorctrl:%s'
|
|
2936
|
-
},
|
|
2937
|
-
{
|
|
2938
|
-
// a=confid:1
|
|
2939
|
-
name: 'bfcpConfId',
|
|
2940
|
-
reg: /^confid:(\d+)/,
|
|
2941
|
-
format: 'confid:%s'
|
|
2942
|
-
},
|
|
2943
|
-
{
|
|
2944
|
-
// a=userid:1
|
|
2945
|
-
name: 'bfcpUserId',
|
|
2946
|
-
reg: /^userid:(\d+)/,
|
|
2947
|
-
format: 'userid:%s'
|
|
2948
|
-
},
|
|
2949
|
-
{
|
|
2950
|
-
// a=floorid:1
|
|
2951
|
-
name: 'bfcpFloorId',
|
|
2952
|
-
reg: /^floorid:(.+) (?:m-stream|mstrm):(.+)/,
|
|
2953
|
-
names: ['id', 'mStream'],
|
|
2954
|
-
format: 'floorid:%s mstrm:%s'
|
|
2955
|
-
},
|
|
2956
|
-
{
|
|
2957
|
-
// any a= that we don't understand is kept verbatim on media.invalid
|
|
2958
|
-
push: 'invalid',
|
|
2959
|
-
names: ['value']
|
|
2960
|
-
}
|
|
2961
|
-
]
|
|
2962
|
-
};
|
|
2963
|
-
|
|
2964
|
-
// set sensible defaults to avoid polluting the grammar with boring details
|
|
2965
|
-
Object.keys(grammar$1).forEach(function (key) {
|
|
2966
|
-
var objs = grammar$1[key];
|
|
2967
|
-
objs.forEach(function (obj) {
|
|
2968
|
-
if (!obj.reg) {
|
|
2969
|
-
obj.reg = /(.*)/;
|
|
2970
|
-
}
|
|
2971
|
-
if (!obj.format) {
|
|
2972
|
-
obj.format = '%s';
|
|
2973
|
-
}
|
|
2974
|
-
});
|
|
2975
|
-
});
|
|
2976
|
-
|
|
2977
|
-
(function (exports) {
|
|
2978
|
-
var toIntIfInt = function (v) {
|
|
2979
|
-
return String(Number(v)) === v ? Number(v) : v;
|
|
2980
|
-
};
|
|
2981
|
-
|
|
2982
|
-
var attachProperties = function (match, location, names, rawName) {
|
|
2983
|
-
if (rawName && !names) {
|
|
2984
|
-
location[rawName] = toIntIfInt(match[1]);
|
|
2985
|
-
}
|
|
2986
|
-
else {
|
|
2987
|
-
for (var i = 0; i < names.length; i += 1) {
|
|
2988
|
-
if (match[i+1] != null) {
|
|
2989
|
-
location[names[i]] = toIntIfInt(match[i+1]);
|
|
2990
|
-
}
|
|
2991
|
-
}
|
|
2992
|
-
}
|
|
2993
|
-
};
|
|
2994
|
-
|
|
2995
|
-
var parseReg = function (obj, location, content) {
|
|
2996
|
-
var needsBlank = obj.name && obj.names;
|
|
2997
|
-
if (obj.push && !location[obj.push]) {
|
|
2998
|
-
location[obj.push] = [];
|
|
2999
|
-
}
|
|
3000
|
-
else if (needsBlank && !location[obj.name]) {
|
|
3001
|
-
location[obj.name] = {};
|
|
3002
|
-
}
|
|
3003
|
-
var keyLocation = obj.push ?
|
|
3004
|
-
{} : // blank object that will be pushed
|
|
3005
|
-
needsBlank ? location[obj.name] : location; // otherwise, named location or root
|
|
3006
|
-
|
|
3007
|
-
attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);
|
|
3008
|
-
|
|
3009
|
-
if (obj.push) {
|
|
3010
|
-
location[obj.push].push(keyLocation);
|
|
3011
|
-
}
|
|
3012
|
-
};
|
|
3013
|
-
|
|
3014
|
-
var grammar = grammar$2.exports;
|
|
3015
|
-
var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);
|
|
3016
|
-
|
|
3017
|
-
exports.parse = function (sdp) {
|
|
3018
|
-
var session = {}
|
|
3019
|
-
, media = []
|
|
3020
|
-
, location = session; // points at where properties go under (one of the above)
|
|
2481
|
+
class Line {
|
|
2482
|
+
}
|
|
3021
2483
|
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
2484
|
+
var _a$5;
|
|
2485
|
+
class BandwidthLine extends Line {
|
|
2486
|
+
constructor(bandwidthType, bandwidth) {
|
|
2487
|
+
super();
|
|
2488
|
+
this.bandwidthType = bandwidthType;
|
|
2489
|
+
this.bandwidth = bandwidth;
|
|
2490
|
+
}
|
|
2491
|
+
static fromSdpLine(line) {
|
|
2492
|
+
if (!BandwidthLine.regex.test(line)) {
|
|
2493
|
+
return undefined;
|
|
2494
|
+
}
|
|
2495
|
+
const tokens = line.match(BandwidthLine.regex);
|
|
2496
|
+
const bandwidthType = tokens[1];
|
|
2497
|
+
const bandwidth = parseInt(tokens[2], 10);
|
|
2498
|
+
return new BandwidthLine(bandwidthType, bandwidth);
|
|
2499
|
+
}
|
|
2500
|
+
toSdpLine() {
|
|
2501
|
+
return `b=${this.bandwidthType}:${this.bandwidth}`;
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
_a$5 = BandwidthLine;
|
|
2505
|
+
BandwidthLine.BW_TYPE_REGEX = 'CT|AS|TIAS';
|
|
2506
|
+
BandwidthLine.regex = new RegExp(`^(${_a$5.BW_TYPE_REGEX}):(${NUM})`);
|
|
2507
|
+
|
|
2508
|
+
class BundleGroupLine extends Line {
|
|
2509
|
+
constructor(mids) {
|
|
2510
|
+
super();
|
|
2511
|
+
this.mids = mids;
|
|
2512
|
+
}
|
|
2513
|
+
static fromSdpLine(line) {
|
|
2514
|
+
if (!BundleGroupLine.regex.test(line)) {
|
|
2515
|
+
return undefined;
|
|
2516
|
+
}
|
|
2517
|
+
const tokens = line.match(BundleGroupLine.regex);
|
|
2518
|
+
const mids = tokens[1].split(' ');
|
|
2519
|
+
return new BundleGroupLine(mids);
|
|
2520
|
+
}
|
|
2521
|
+
toSdpLine() {
|
|
2522
|
+
return `a=group:BUNDLE ${this.mids.join(' ')}`;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
BundleGroupLine.regex = new RegExp(`^group:BUNDLE (${REST})`);
|
|
2526
|
+
|
|
2527
|
+
var _a$4;
|
|
2528
|
+
class CandidateLine extends Line {
|
|
2529
|
+
constructor(foundation, componentId, transport, priority, connectionAddress, port, candidateType, relAddr, relPort, candidateExtensions) {
|
|
2530
|
+
super();
|
|
2531
|
+
this.foundation = foundation;
|
|
2532
|
+
this.componentId = componentId;
|
|
2533
|
+
this.transport = transport;
|
|
2534
|
+
this.priority = priority;
|
|
2535
|
+
this.connectionAddress = connectionAddress;
|
|
2536
|
+
this.port = port;
|
|
2537
|
+
this.candidateType = candidateType;
|
|
2538
|
+
this.relAddr = relAddr;
|
|
2539
|
+
this.relPort = relPort;
|
|
2540
|
+
this.candidateExtensions = candidateExtensions;
|
|
2541
|
+
}
|
|
2542
|
+
static fromSdpLine(line) {
|
|
2543
|
+
if (!CandidateLine.regex.test(line)) {
|
|
2544
|
+
return undefined;
|
|
2545
|
+
}
|
|
2546
|
+
const tokens = line.match(CandidateLine.regex);
|
|
2547
|
+
const foundation = tokens[1];
|
|
2548
|
+
const componentId = parseInt(tokens[2], 10);
|
|
2549
|
+
const transport = tokens[3];
|
|
2550
|
+
const priority = parseInt(tokens[4], 10);
|
|
2551
|
+
const connectionAddress = tokens[5];
|
|
2552
|
+
const port = parseInt(tokens[6], 10);
|
|
2553
|
+
const candidateType = tokens[7];
|
|
2554
|
+
const relAddr = tokens[8];
|
|
2555
|
+
const relPort = tokens[9] ? parseInt(tokens[9], 10) : undefined;
|
|
2556
|
+
const candidateExtensions = tokens[10];
|
|
2557
|
+
return new CandidateLine(foundation, componentId, transport, priority, connectionAddress, port, candidateType, relAddr, relPort, candidateExtensions);
|
|
2558
|
+
}
|
|
2559
|
+
toSdpLine() {
|
|
2560
|
+
let str = '';
|
|
2561
|
+
str += `a=candidate:${this.foundation} ${this.componentId} ${this.transport} ${this.priority} ${this.connectionAddress} ${this.port} typ ${this.candidateType}`;
|
|
2562
|
+
if (this.relAddr) {
|
|
2563
|
+
str += ` raddr ${this.relAddr}`;
|
|
2564
|
+
}
|
|
2565
|
+
if (this.relPort) {
|
|
2566
|
+
str += ` rport ${this.relPort}`;
|
|
2567
|
+
}
|
|
2568
|
+
if (this.candidateExtensions) {
|
|
2569
|
+
str += ` ${this.candidateExtensions}`;
|
|
2570
|
+
}
|
|
2571
|
+
return str;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
_a$4 = CandidateLine;
|
|
2575
|
+
CandidateLine.ICE_CHARS = `[a-zA-Z0-9+/]+`;
|
|
2576
|
+
CandidateLine.regex = new RegExp(`^candidate:(${_a$4.ICE_CHARS}) (${NUM}) (${TOKEN}) (${NUM}) (${TOKEN}) (${NUM}) typ (${TOKEN})(?: raddr (${TOKEN}))?(?: rport (${NUM}))?(?: (${REST}))?`);
|
|
2577
|
+
|
|
2578
|
+
class ConnectionLine extends Line {
|
|
2579
|
+
constructor(netType, addrType, ipAddr) {
|
|
2580
|
+
super();
|
|
2581
|
+
this.netType = netType;
|
|
2582
|
+
this.addrType = addrType;
|
|
2583
|
+
this.ipAddr = ipAddr;
|
|
2584
|
+
}
|
|
2585
|
+
static fromSdpLine(line) {
|
|
2586
|
+
if (!ConnectionLine.regex.test(line)) {
|
|
2587
|
+
return undefined;
|
|
2588
|
+
}
|
|
2589
|
+
const tokens = line.match(ConnectionLine.regex);
|
|
2590
|
+
const netType = tokens[1];
|
|
2591
|
+
const addrType = tokens[2];
|
|
2592
|
+
const ipAddr = tokens[3];
|
|
2593
|
+
return new ConnectionLine(netType, addrType, ipAddr);
|
|
2594
|
+
}
|
|
2595
|
+
toSdpLine() {
|
|
2596
|
+
return `c=${this.netType} ${this.addrType} ${this.ipAddr}`;
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
ConnectionLine.regex = new RegExp(`^(${TOKEN}) (${TOKEN}) (${TOKEN})`);
|
|
3030
2600
|
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
2601
|
+
class ContentLine extends Line {
|
|
2602
|
+
constructor(values) {
|
|
2603
|
+
super();
|
|
2604
|
+
this.values = values;
|
|
2605
|
+
}
|
|
2606
|
+
static fromSdpLine(line) {
|
|
2607
|
+
if (!ContentLine.regex.test(line)) {
|
|
2608
|
+
return undefined;
|
|
2609
|
+
}
|
|
2610
|
+
const tokens = line.match(ContentLine.regex);
|
|
2611
|
+
const values = tokens[1].split(',');
|
|
2612
|
+
return new ContentLine(values);
|
|
2613
|
+
}
|
|
2614
|
+
toSdpLine() {
|
|
2615
|
+
return `a=content:${this.values.join(',')}`;
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
ContentLine.regex = new RegExp(`^content:(${REST})$`);
|
|
3038
2619
|
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
2620
|
+
class DirectionLine extends Line {
|
|
2621
|
+
constructor(direction) {
|
|
2622
|
+
super();
|
|
2623
|
+
this.direction = direction;
|
|
2624
|
+
}
|
|
2625
|
+
static fromSdpLine(line) {
|
|
2626
|
+
if (!DirectionLine.regex.test(line)) {
|
|
2627
|
+
return undefined;
|
|
2628
|
+
}
|
|
2629
|
+
const tokens = line.match(DirectionLine.regex);
|
|
2630
|
+
const direction = tokens[1];
|
|
2631
|
+
return new DirectionLine(direction);
|
|
2632
|
+
}
|
|
2633
|
+
toSdpLine() {
|
|
2634
|
+
return `a=${this.direction}`;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
DirectionLine.regex = /^(sendrecv|sendonly|recvonly|inactive)$/;
|
|
2638
|
+
|
|
2639
|
+
var _a$3;
|
|
2640
|
+
class ExtMapLine extends Line {
|
|
2641
|
+
constructor(id, uri, direction, extensionAttributes) {
|
|
2642
|
+
super();
|
|
2643
|
+
this.id = id;
|
|
2644
|
+
this.uri = uri;
|
|
2645
|
+
this.direction = direction;
|
|
2646
|
+
this.extensionAttributes = extensionAttributes;
|
|
2647
|
+
}
|
|
2648
|
+
static fromSdpLine(line) {
|
|
2649
|
+
if (!ExtMapLine.regex.test(line)) {
|
|
2650
|
+
return undefined;
|
|
2651
|
+
}
|
|
2652
|
+
const tokens = line.match(ExtMapLine.regex);
|
|
2653
|
+
const id = parseInt(tokens[1], 10);
|
|
2654
|
+
const direction = tokens[2];
|
|
2655
|
+
const uri = tokens[3];
|
|
2656
|
+
const extensionAttributes = tokens[4];
|
|
2657
|
+
return new ExtMapLine(id, uri, direction, extensionAttributes);
|
|
2658
|
+
}
|
|
2659
|
+
toSdpLine() {
|
|
2660
|
+
let str = '';
|
|
2661
|
+
str += `a=extmap:${this.id}`;
|
|
2662
|
+
if (this.direction) {
|
|
2663
|
+
str += `/${this.direction}`;
|
|
2664
|
+
}
|
|
2665
|
+
str += ` ${this.uri}`;
|
|
2666
|
+
if (this.extensionAttributes) {
|
|
2667
|
+
str += ` ${this.extensionAttributes}`;
|
|
2668
|
+
}
|
|
2669
|
+
return str;
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
_a$3 = ExtMapLine;
|
|
2673
|
+
ExtMapLine.EXTMAP_DIRECTION = `sendonly|recvonly|sendrecv|inactive`;
|
|
2674
|
+
ExtMapLine.regex = new RegExp(`^extmap:(${NUM})(?:/(${_a$3.EXTMAP_DIRECTION}))? (${TOKEN})(?: (${REST}))?`);
|
|
2675
|
+
|
|
2676
|
+
class FingerprintLine extends Line {
|
|
2677
|
+
constructor(fingerprint) {
|
|
2678
|
+
super();
|
|
2679
|
+
this.fingerprint = fingerprint;
|
|
2680
|
+
}
|
|
2681
|
+
static fromSdpLine(line) {
|
|
2682
|
+
if (!FingerprintLine.regex.test(line)) {
|
|
2683
|
+
return undefined;
|
|
2684
|
+
}
|
|
2685
|
+
const tokens = line.match(FingerprintLine.regex);
|
|
2686
|
+
const fingerprint = tokens[1];
|
|
2687
|
+
return new FingerprintLine(fingerprint);
|
|
2688
|
+
}
|
|
2689
|
+
toSdpLine() {
|
|
2690
|
+
return `a=fingerprint:${this.fingerprint}`;
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
FingerprintLine.regex = new RegExp(`^fingerprint:(${REST})`);
|
|
3042
2694
|
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
2695
|
+
class FmtpLine extends Line {
|
|
2696
|
+
constructor(payloadType, params) {
|
|
2697
|
+
super();
|
|
2698
|
+
this.payloadType = payloadType;
|
|
2699
|
+
this.params = params;
|
|
2700
|
+
}
|
|
2701
|
+
static fromSdpLine(line) {
|
|
2702
|
+
if (!FmtpLine.regex.test(line)) {
|
|
2703
|
+
return undefined;
|
|
2704
|
+
}
|
|
2705
|
+
const tokens = line.match(FmtpLine.regex);
|
|
2706
|
+
const payloadType = parseInt(tokens[1], 10);
|
|
2707
|
+
const params = tokens[2];
|
|
2708
|
+
return new FmtpLine(payloadType, params);
|
|
2709
|
+
}
|
|
2710
|
+
toSdpLine() {
|
|
2711
|
+
return `a=fmtp:${this.payloadType} ${this.params}`;
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
FmtpLine.regex = new RegExp(`^fmtp:(${NUM}) (${REST})`);
|
|
3052
2715
|
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
2716
|
+
class IceOptionsLine extends Line {
|
|
2717
|
+
constructor(options) {
|
|
2718
|
+
super();
|
|
2719
|
+
this.options = options;
|
|
2720
|
+
}
|
|
2721
|
+
static fromSdpLine(line) {
|
|
2722
|
+
if (!IceOptionsLine.regex.test(line)) {
|
|
2723
|
+
return undefined;
|
|
2724
|
+
}
|
|
2725
|
+
const tokens = line.match(IceOptionsLine.regex);
|
|
2726
|
+
const options = tokens[1].split(' ');
|
|
2727
|
+
return new IceOptionsLine(options);
|
|
2728
|
+
}
|
|
2729
|
+
toSdpLine() {
|
|
2730
|
+
return `a=ice-options:${this.options.join(' ')}`;
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
IceOptionsLine.regex = new RegExp(`^ice-options:(${REST})$`);
|
|
3056
2734
|
|
|
3057
|
-
|
|
3058
|
-
|
|
2735
|
+
class IcePwdLine extends Line {
|
|
2736
|
+
constructor(pwd) {
|
|
2737
|
+
super();
|
|
2738
|
+
this.pwd = pwd;
|
|
2739
|
+
}
|
|
2740
|
+
static fromSdpLine(line) {
|
|
2741
|
+
if (!IcePwdLine.regex.test(line)) {
|
|
2742
|
+
return undefined;
|
|
2743
|
+
}
|
|
2744
|
+
const tokens = line.match(IcePwdLine.regex);
|
|
2745
|
+
const pwd = tokens[1];
|
|
2746
|
+
return new IcePwdLine(pwd);
|
|
2747
|
+
}
|
|
2748
|
+
toSdpLine() {
|
|
2749
|
+
return `a=ice-pwd:${this.pwd}`;
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
IcePwdLine.regex = new RegExp(`^ice-pwd:(${TOKEN})$`);
|
|
3059
2753
|
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
2754
|
+
class IceUfragLine extends Line {
|
|
2755
|
+
constructor(ufrag) {
|
|
2756
|
+
super();
|
|
2757
|
+
this.ufrag = ufrag;
|
|
2758
|
+
}
|
|
2759
|
+
static fromSdpLine(line) {
|
|
2760
|
+
if (!IceUfragLine.regex.test(line)) {
|
|
2761
|
+
return undefined;
|
|
2762
|
+
}
|
|
2763
|
+
const tokens = line.match(IceUfragLine.regex);
|
|
2764
|
+
const ufrag = tokens[1];
|
|
2765
|
+
return new IceUfragLine(ufrag);
|
|
2766
|
+
}
|
|
2767
|
+
toSdpLine() {
|
|
2768
|
+
return `a=ice-ufrag:${this.ufrag}`;
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
IceUfragLine.regex = new RegExp(`^ice-ufrag:(${TOKEN})$`);
|
|
3063
2772
|
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
2773
|
+
class MaxMessageSizeLine extends Line {
|
|
2774
|
+
constructor(maxMessageSize) {
|
|
2775
|
+
super();
|
|
2776
|
+
this.maxMessageSize = maxMessageSize;
|
|
2777
|
+
}
|
|
2778
|
+
static fromSdpLine(line) {
|
|
2779
|
+
if (!MaxMessageSizeLine.regex.test(line)) {
|
|
2780
|
+
return undefined;
|
|
2781
|
+
}
|
|
2782
|
+
const tokens = line.match(MaxMessageSizeLine.regex);
|
|
2783
|
+
const maxMessageSize = parseInt(tokens[1], 10);
|
|
2784
|
+
return new MaxMessageSizeLine(maxMessageSize);
|
|
2785
|
+
}
|
|
2786
|
+
toSdpLine() {
|
|
2787
|
+
return `a=max-message-size:${this.maxMessageSize}`;
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
MaxMessageSizeLine.regex = new RegExp(`^max-message-size:(${NUM})`);
|
|
2791
|
+
|
|
2792
|
+
var _a$2;
|
|
2793
|
+
class MediaLine extends Line {
|
|
2794
|
+
constructor(type, port, protocol, formats) {
|
|
2795
|
+
super();
|
|
2796
|
+
this.type = type;
|
|
2797
|
+
this.port = port;
|
|
2798
|
+
this.protocol = protocol;
|
|
2799
|
+
this.formats = formats;
|
|
2800
|
+
}
|
|
2801
|
+
static fromSdpLine(line) {
|
|
2802
|
+
if (!MediaLine.regex.test(line)) {
|
|
2803
|
+
return undefined;
|
|
2804
|
+
}
|
|
2805
|
+
const tokens = line.match(MediaLine.regex);
|
|
2806
|
+
const type = tokens[1];
|
|
2807
|
+
const port = parseInt(tokens[2], 10);
|
|
2808
|
+
const protocol = tokens[3];
|
|
2809
|
+
const formats = tokens[4].split(' ');
|
|
2810
|
+
return new MediaLine(type, port, protocol, formats);
|
|
2811
|
+
}
|
|
2812
|
+
toSdpLine() {
|
|
2813
|
+
return `m=${this.type} ${this.port} ${this.protocol} ${this.formats.join(' ')}`;
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
_a$2 = MediaLine;
|
|
2817
|
+
MediaLine.MEDIA_TYPE = 'audio|video|application';
|
|
2818
|
+
MediaLine.regex = new RegExp(`^(${_a$2.MEDIA_TYPE}) (${NUM}) (${TOKEN}) (${REST})`);
|
|
2819
|
+
|
|
2820
|
+
class MidLine extends Line {
|
|
2821
|
+
constructor(mid) {
|
|
2822
|
+
super();
|
|
2823
|
+
this.mid = mid;
|
|
2824
|
+
}
|
|
2825
|
+
static fromSdpLine(line) {
|
|
2826
|
+
if (!MidLine.regex.test(line)) {
|
|
2827
|
+
return undefined;
|
|
2828
|
+
}
|
|
2829
|
+
const tokens = line.match(MidLine.regex);
|
|
2830
|
+
const mid = tokens[1];
|
|
2831
|
+
return new MidLine(mid);
|
|
2832
|
+
}
|
|
2833
|
+
toSdpLine() {
|
|
2834
|
+
return `a=mid:${this.mid}`;
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
MidLine.regex = new RegExp(`^mid:(${TOKEN})$`);
|
|
2838
|
+
|
|
2839
|
+
class OriginLine extends Line {
|
|
2840
|
+
constructor(username, sessionId, sessionVersion, netType, addrType, ipAddr) {
|
|
2841
|
+
super();
|
|
2842
|
+
this.username = username;
|
|
2843
|
+
this.sessionId = sessionId;
|
|
2844
|
+
this.sessionVersion = sessionVersion;
|
|
2845
|
+
this.netType = netType;
|
|
2846
|
+
this.addrType = addrType;
|
|
2847
|
+
this.ipAddr = ipAddr;
|
|
2848
|
+
}
|
|
2849
|
+
static fromSdpLine(line) {
|
|
2850
|
+
if (!OriginLine.regex.test(line)) {
|
|
2851
|
+
return undefined;
|
|
2852
|
+
}
|
|
2853
|
+
const tokens = line.match(OriginLine.regex);
|
|
2854
|
+
const username = tokens[1];
|
|
2855
|
+
const sessionId = tokens[2];
|
|
2856
|
+
const sessionVersion = parseInt(tokens[3], 10);
|
|
2857
|
+
const netType = tokens[4];
|
|
2858
|
+
const addrType = tokens[5];
|
|
2859
|
+
const ipAddr = tokens[6];
|
|
2860
|
+
return new OriginLine(username, sessionId, sessionVersion, netType, addrType, ipAddr);
|
|
2861
|
+
}
|
|
2862
|
+
toSdpLine() {
|
|
2863
|
+
return `o=${this.username} ${this.sessionId} ${this.sessionVersion} ${this.netType} ${this.addrType} ${this.ipAddr}`;
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
OriginLine.regex = new RegExp(`^(${TOKEN}) (${TOKEN}) (${NUM}) (${TOKEN}) (${TOKEN}) (${TOKEN})`);
|
|
2867
|
+
|
|
2868
|
+
var _a$1;
|
|
2869
|
+
class RidLine extends Line {
|
|
2870
|
+
constructor(id, direction, params) {
|
|
2871
|
+
super();
|
|
2872
|
+
this.id = id;
|
|
2873
|
+
this.direction = direction;
|
|
2874
|
+
this.params = params;
|
|
2875
|
+
}
|
|
2876
|
+
static fromSdpLine(line) {
|
|
2877
|
+
if (!RidLine.regex.test(line)) {
|
|
2878
|
+
return undefined;
|
|
2879
|
+
}
|
|
2880
|
+
const tokens = line.match(RidLine.regex);
|
|
2881
|
+
const id = tokens[1];
|
|
2882
|
+
const direction = tokens[2];
|
|
2883
|
+
const params = tokens[3];
|
|
2884
|
+
return new RidLine(id, direction, params);
|
|
2885
|
+
}
|
|
2886
|
+
toSdpLine() {
|
|
2887
|
+
let str = '';
|
|
2888
|
+
str += `a=rid:${this.id} ${this.direction}`;
|
|
2889
|
+
if (this.params) {
|
|
2890
|
+
str += ` ${this.params}`;
|
|
2891
|
+
}
|
|
2892
|
+
return str;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
_a$1 = RidLine;
|
|
2896
|
+
RidLine.RID_ID = `[\\w-]+`;
|
|
2897
|
+
RidLine.RID_DIRECTION = `\\bsend\\b|\\brecv\\b`;
|
|
2898
|
+
RidLine.regex = new RegExp(`^rid:(${_a$1.RID_ID}) (${_a$1.RID_DIRECTION})(?:${SP}(${REST}))?`);
|
|
2899
|
+
|
|
2900
|
+
class RtcpMuxLine extends Line {
|
|
2901
|
+
static fromSdpLine(line) {
|
|
2902
|
+
if (!RtcpMuxLine.regex.test(line)) {
|
|
2903
|
+
return undefined;
|
|
2904
|
+
}
|
|
2905
|
+
return new RtcpMuxLine();
|
|
2906
|
+
}
|
|
2907
|
+
toSdpLine() {
|
|
2908
|
+
return `a=rtcp-mux`;
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
RtcpMuxLine.regex = /^rtcp-mux$/;
|
|
3076
2912
|
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
2913
|
+
class RtcpFbLine extends Line {
|
|
2914
|
+
constructor(payloadType, feedback) {
|
|
2915
|
+
super();
|
|
2916
|
+
this.payloadType = payloadType;
|
|
2917
|
+
this.feedback = feedback;
|
|
2918
|
+
}
|
|
2919
|
+
static fromSdpLine(line) {
|
|
2920
|
+
if (!RtcpFbLine.regex.test(line)) {
|
|
2921
|
+
return undefined;
|
|
2922
|
+
}
|
|
2923
|
+
const tokens = line.match(RtcpFbLine.regex);
|
|
2924
|
+
const payloadType = parseInt(tokens[1], 10);
|
|
2925
|
+
const feedback = tokens[2];
|
|
2926
|
+
return new RtcpFbLine(payloadType, feedback);
|
|
2927
|
+
}
|
|
2928
|
+
toSdpLine() {
|
|
2929
|
+
return `a=rtcp-fb:${this.payloadType} ${this.feedback}`;
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
RtcpFbLine.regex = new RegExp(`^rtcp-fb:(${NUM}) (${REST})`);
|
|
2933
|
+
|
|
2934
|
+
var _a$6;
|
|
2935
|
+
class RtpMapLine extends Line {
|
|
2936
|
+
constructor(payloadType, encodingName, clockRate, encodingParams) {
|
|
2937
|
+
super();
|
|
2938
|
+
this.payloadType = payloadType;
|
|
2939
|
+
this.encodingName = encodingName;
|
|
2940
|
+
this.clockRate = clockRate;
|
|
2941
|
+
this.encodingParams = encodingParams;
|
|
2942
|
+
}
|
|
2943
|
+
static fromSdpLine(line) {
|
|
2944
|
+
if (!RtpMapLine.regex.test(line)) {
|
|
2945
|
+
return undefined;
|
|
2946
|
+
}
|
|
2947
|
+
const tokens = line.match(RtpMapLine.regex);
|
|
2948
|
+
const payloadType = parseInt(tokens[1], 10);
|
|
2949
|
+
const encodingName = tokens[2];
|
|
2950
|
+
const clockRate = parseInt(tokens[3], 10);
|
|
2951
|
+
const encodingParams = tokens[4];
|
|
2952
|
+
return new RtpMapLine(payloadType, encodingName, clockRate, encodingParams);
|
|
2953
|
+
}
|
|
2954
|
+
toSdpLine() {
|
|
2955
|
+
let str = '';
|
|
2956
|
+
str += `a=rtpmap:${this.payloadType} ${this.encodingName}/${this.clockRate}`;
|
|
2957
|
+
if (this.encodingParams) {
|
|
2958
|
+
str += `/${this.encodingParams}`;
|
|
2959
|
+
}
|
|
2960
|
+
return str;
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
_a$6 = RtpMapLine;
|
|
2964
|
+
RtpMapLine.NON_SLASH_TOKEN = '[^\\s/]+';
|
|
2965
|
+
RtpMapLine.regex = new RegExp(`^rtpmap:(${NUM}) (${_a$6.NON_SLASH_TOKEN})/(${_a$6.NON_SLASH_TOKEN})(?:/(${_a$6.NON_SLASH_TOKEN}))?`);
|
|
2966
|
+
|
|
2967
|
+
class SctpPortLine extends Line {
|
|
2968
|
+
constructor(port) {
|
|
2969
|
+
super();
|
|
2970
|
+
this.port = port;
|
|
2971
|
+
}
|
|
2972
|
+
static fromSdpLine(line) {
|
|
2973
|
+
if (!SctpPortLine.regex.test(line)) {
|
|
2974
|
+
return undefined;
|
|
2975
|
+
}
|
|
2976
|
+
const tokens = line.match(SctpPortLine.regex);
|
|
2977
|
+
const port = parseInt(tokens[1], 10);
|
|
2978
|
+
return new SctpPortLine(port);
|
|
2979
|
+
}
|
|
2980
|
+
toSdpLine() {
|
|
2981
|
+
return `a=sctp-port:${this.port}`;
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
SctpPortLine.regex = new RegExp(`^sctp-port:(${NUM})`);
|
|
3082
2985
|
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
2986
|
+
class SessionInformationLine extends Line {
|
|
2987
|
+
constructor(info) {
|
|
2988
|
+
super();
|
|
2989
|
+
this.info = info;
|
|
2990
|
+
}
|
|
2991
|
+
static fromSdpLine(line) {
|
|
2992
|
+
if (!SessionInformationLine.regex.test(line)) {
|
|
2993
|
+
return undefined;
|
|
2994
|
+
}
|
|
2995
|
+
const tokens = line.match(SessionInformationLine.regex);
|
|
2996
|
+
const info = tokens[1];
|
|
2997
|
+
return new SessionInformationLine(info);
|
|
2998
|
+
}
|
|
2999
|
+
toSdpLine() {
|
|
3000
|
+
return `i=${this.info}`;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
SessionInformationLine.regex = new RegExp(`(${REST})`);
|
|
3087
3004
|
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3005
|
+
class SessionNameLine extends Line {
|
|
3006
|
+
constructor(name) {
|
|
3007
|
+
super();
|
|
3008
|
+
this.name = name;
|
|
3009
|
+
}
|
|
3010
|
+
static fromSdpLine(line) {
|
|
3011
|
+
if (!SessionNameLine.regex.test(line)) {
|
|
3012
|
+
return undefined;
|
|
3013
|
+
}
|
|
3014
|
+
const tokens = line.match(SessionNameLine.regex);
|
|
3015
|
+
const name = tokens[1];
|
|
3016
|
+
return new SessionNameLine(name);
|
|
3017
|
+
}
|
|
3018
|
+
toSdpLine() {
|
|
3019
|
+
return `s=${this.name}`;
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
SessionNameLine.regex = new RegExp(`^(${REST})`);
|
|
3094
3023
|
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
}
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
if (i >= len) {
|
|
3114
|
-
return x; // missing argument
|
|
3115
|
-
}
|
|
3116
|
-
var arg = args[i];
|
|
3117
|
-
i += 1;
|
|
3118
|
-
switch (x) {
|
|
3119
|
-
case '%%':
|
|
3120
|
-
return '%';
|
|
3121
|
-
case '%s':
|
|
3122
|
-
return String(arg);
|
|
3123
|
-
case '%d':
|
|
3124
|
-
return Number(arg);
|
|
3125
|
-
case '%v':
|
|
3126
|
-
return '';
|
|
3127
|
-
}
|
|
3128
|
-
});
|
|
3129
|
-
// NB: we discard excess arguments - they are typically undefined from makeLine
|
|
3130
|
-
};
|
|
3024
|
+
class SetupLine extends Line {
|
|
3025
|
+
constructor(setup) {
|
|
3026
|
+
super();
|
|
3027
|
+
this.setup = setup;
|
|
3028
|
+
}
|
|
3029
|
+
static fromSdpLine(line) {
|
|
3030
|
+
if (!SetupLine.regex.test(line)) {
|
|
3031
|
+
return undefined;
|
|
3032
|
+
}
|
|
3033
|
+
const tokens = line.match(SetupLine.regex);
|
|
3034
|
+
const setup = tokens[1];
|
|
3035
|
+
return new SetupLine(setup);
|
|
3036
|
+
}
|
|
3037
|
+
toSdpLine() {
|
|
3038
|
+
return `a=setup:${this.setup}`;
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
SetupLine.regex = /^setup:(actpass|active|passive)$/;
|
|
3131
3042
|
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3043
|
+
class SimulcastLayer {
|
|
3044
|
+
constructor(id, paused) {
|
|
3045
|
+
this.id = id;
|
|
3046
|
+
this.paused = paused;
|
|
3047
|
+
}
|
|
3048
|
+
toString() {
|
|
3049
|
+
return this.paused ? `~${this.id}` : this.id;
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
class SimulcastLayerList {
|
|
3053
|
+
constructor() {
|
|
3054
|
+
this.layers = [];
|
|
3055
|
+
}
|
|
3056
|
+
addLayer(layer) {
|
|
3057
|
+
this.layers.push([layer]);
|
|
3058
|
+
}
|
|
3059
|
+
addLayerWithAlternatives(alternatives) {
|
|
3060
|
+
this.layers.push(alternatives);
|
|
3061
|
+
}
|
|
3062
|
+
get length() {
|
|
3063
|
+
return this.layers.length;
|
|
3064
|
+
}
|
|
3065
|
+
get(index) {
|
|
3066
|
+
return this.layers[index];
|
|
3067
|
+
}
|
|
3068
|
+
static fromString(str) {
|
|
3069
|
+
const layerList = new SimulcastLayerList();
|
|
3070
|
+
const tokens = str.split(';');
|
|
3071
|
+
if (tokens.length === 1 && !tokens[0].trim()) {
|
|
3072
|
+
throw new Error('simulcast stream list empty');
|
|
3073
|
+
}
|
|
3074
|
+
tokens.forEach((token) => {
|
|
3075
|
+
if (!token) {
|
|
3076
|
+
throw new Error('simulcast layer list empty');
|
|
3077
|
+
}
|
|
3078
|
+
const ridTokens = token.split(',');
|
|
3079
|
+
const layers = [];
|
|
3080
|
+
ridTokens.forEach((ridToken) => {
|
|
3081
|
+
if (!ridToken || ridToken === '~') {
|
|
3082
|
+
throw new Error('rid empty');
|
|
3083
|
+
}
|
|
3084
|
+
const paused = ridToken[0] === '~';
|
|
3085
|
+
const rid = paused ? ridToken.substring(1) : ridToken;
|
|
3086
|
+
layers.push(new SimulcastLayer(rid, paused));
|
|
3087
|
+
});
|
|
3088
|
+
layerList.addLayerWithAlternatives(layers);
|
|
3089
|
+
});
|
|
3090
|
+
return layerList;
|
|
3091
|
+
}
|
|
3092
|
+
toString() {
|
|
3093
|
+
return this.layers
|
|
3094
|
+
.map((altArray) => altArray.map((v) => v.toString()).join(','))
|
|
3095
|
+
.join(';');
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
class SimulcastLine extends Line {
|
|
3099
|
+
constructor(sendLayers, recvLayers) {
|
|
3100
|
+
super();
|
|
3101
|
+
this.sendLayers = sendLayers;
|
|
3102
|
+
this.recvLayers = recvLayers;
|
|
3103
|
+
}
|
|
3104
|
+
static fromSdpLine(line) {
|
|
3105
|
+
if (!SimulcastLine.regex.test(line)) {
|
|
3106
|
+
return undefined;
|
|
3107
|
+
}
|
|
3108
|
+
const tokens = line.match(SimulcastLine.regex);
|
|
3109
|
+
const bidirectional = tokens[3] && tokens[4];
|
|
3110
|
+
const firstDirection = tokens[1];
|
|
3111
|
+
const layerList1 = SimulcastLayerList.fromString(tokens[2]);
|
|
3112
|
+
let layerList2 = new SimulcastLayerList();
|
|
3113
|
+
if (bidirectional) {
|
|
3114
|
+
const secondDirection = tokens[3];
|
|
3115
|
+
if (firstDirection === secondDirection) {
|
|
3116
|
+
return undefined;
|
|
3117
|
+
}
|
|
3118
|
+
layerList2 = SimulcastLayerList.fromString(tokens[4]);
|
|
3119
|
+
}
|
|
3120
|
+
let sendLayerList;
|
|
3121
|
+
let recvLayerList;
|
|
3122
|
+
if (firstDirection === 'send') {
|
|
3123
|
+
sendLayerList = layerList1;
|
|
3124
|
+
recvLayerList = layerList2;
|
|
3125
|
+
}
|
|
3126
|
+
else {
|
|
3127
|
+
sendLayerList = layerList2;
|
|
3128
|
+
recvLayerList = layerList1;
|
|
3129
|
+
}
|
|
3130
|
+
return new SimulcastLine(sendLayerList, recvLayerList);
|
|
3131
|
+
}
|
|
3132
|
+
toSdpLine() {
|
|
3133
|
+
let str = 'a=simulcast:';
|
|
3134
|
+
if (this.sendLayers.length) {
|
|
3135
|
+
str += `send ${this.sendLayers.toString()}`;
|
|
3136
|
+
if (this.recvLayers.length) {
|
|
3137
|
+
str += ` `;
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
if (this.recvLayers.length) {
|
|
3141
|
+
str += `recv ${this.recvLayers.toString()}`;
|
|
3142
|
+
}
|
|
3143
|
+
return str;
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
SimulcastLine.regex = new RegExp(`^simulcast:(send|recv) (${TOKEN})(?: (send|recv) (${TOKEN}))?`);
|
|
3136
3147
|
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
}
|
|
3148
|
+
class TimingLine extends Line {
|
|
3149
|
+
constructor(startTime, stopTime) {
|
|
3150
|
+
super();
|
|
3151
|
+
this.startTime = startTime;
|
|
3152
|
+
this.stopTime = stopTime;
|
|
3153
|
+
}
|
|
3154
|
+
static fromSdpLine(line) {
|
|
3155
|
+
if (!TimingLine.regex.test(line)) {
|
|
3156
|
+
return undefined;
|
|
3157
|
+
}
|
|
3158
|
+
const tokens = line.match(TimingLine.regex);
|
|
3159
|
+
const startTime = parseInt(tokens[1], 10);
|
|
3160
|
+
const stopTime = parseInt(tokens[2], 10);
|
|
3161
|
+
return new TimingLine(startTime, stopTime);
|
|
3162
|
+
}
|
|
3163
|
+
toSdpLine() {
|
|
3164
|
+
return `t=${this.startTime} ${this.stopTime}`;
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
TimingLine.regex = new RegExp(`^(${NUM}) (${NUM})`);
|
|
3154
3168
|
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3169
|
+
class VersionLine extends Line {
|
|
3170
|
+
constructor(version) {
|
|
3171
|
+
super();
|
|
3172
|
+
this.version = version;
|
|
3173
|
+
}
|
|
3174
|
+
static fromSdpLine(line) {
|
|
3175
|
+
if (!VersionLine.regex.test(line)) {
|
|
3176
|
+
return undefined;
|
|
3177
|
+
}
|
|
3178
|
+
const tokens = line.match(VersionLine.regex);
|
|
3179
|
+
const version = parseInt(tokens[1], 10);
|
|
3180
|
+
return new VersionLine(version);
|
|
3181
|
+
}
|
|
3182
|
+
toSdpLine() {
|
|
3183
|
+
return `v=${this.version}`;
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
VersionLine.regex = new RegExp(`^(${NUM})$`);
|
|
3163
3187
|
|
|
3188
|
+
class UnknownLine extends Line {
|
|
3189
|
+
constructor(value) {
|
|
3190
|
+
super();
|
|
3191
|
+
this.value = value;
|
|
3192
|
+
}
|
|
3193
|
+
static fromSdpLine(line) {
|
|
3194
|
+
const tokens = line.match(UnknownLine.regex);
|
|
3195
|
+
const value = tokens[1];
|
|
3196
|
+
return new UnknownLine(value);
|
|
3197
|
+
}
|
|
3198
|
+
toSdpLine() {
|
|
3199
|
+
return `${this.value}`;
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
UnknownLine.regex = new RegExp(`(${REST})`);
|
|
3164
3203
|
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3204
|
+
class IceInfo {
|
|
3205
|
+
constructor() {
|
|
3206
|
+
this.candidates = [];
|
|
3207
|
+
}
|
|
3208
|
+
addLine(line) {
|
|
3209
|
+
if (line instanceof IceUfragLine) {
|
|
3210
|
+
this.ufrag = line;
|
|
3211
|
+
return true;
|
|
3212
|
+
}
|
|
3213
|
+
if (line instanceof IcePwdLine) {
|
|
3214
|
+
this.pwd = line;
|
|
3215
|
+
return true;
|
|
3216
|
+
}
|
|
3217
|
+
if (line instanceof IceOptionsLine) {
|
|
3218
|
+
this.options = line;
|
|
3219
|
+
return true;
|
|
3220
|
+
}
|
|
3221
|
+
if (line instanceof CandidateLine) {
|
|
3222
|
+
this.candidates.push(line);
|
|
3223
|
+
return true;
|
|
3224
|
+
}
|
|
3225
|
+
return false;
|
|
3226
|
+
}
|
|
3227
|
+
toLines() {
|
|
3228
|
+
const lines = [];
|
|
3229
|
+
if (this.ufrag) {
|
|
3230
|
+
lines.push(this.ufrag);
|
|
3231
|
+
}
|
|
3232
|
+
if (this.pwd) {
|
|
3233
|
+
lines.push(this.pwd);
|
|
3234
|
+
}
|
|
3235
|
+
if (this.options) {
|
|
3236
|
+
lines.push(this.options);
|
|
3237
|
+
}
|
|
3238
|
+
this.candidates.forEach((candidate) => lines.push(candidate));
|
|
3239
|
+
return lines;
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3179
3242
|
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3243
|
+
class MediaDescription {
|
|
3244
|
+
constructor(type, port, protocol) {
|
|
3245
|
+
this.iceInfo = new IceInfo();
|
|
3246
|
+
this.otherLines = [];
|
|
3247
|
+
this.type = type;
|
|
3248
|
+
this.port = port;
|
|
3249
|
+
this.protocol = protocol;
|
|
3250
|
+
}
|
|
3251
|
+
findOtherLine(ty) {
|
|
3252
|
+
return this.otherLines.find((line) => line instanceof ty);
|
|
3253
|
+
}
|
|
3254
|
+
addLine(line) {
|
|
3255
|
+
if (line instanceof BundleGroupLine) {
|
|
3256
|
+
throw new Error(`Error: bundle group line not allowed in media description`);
|
|
3257
|
+
}
|
|
3258
|
+
if (line instanceof BandwidthLine) {
|
|
3259
|
+
this.bandwidth = line;
|
|
3260
|
+
return true;
|
|
3261
|
+
}
|
|
3262
|
+
if (line instanceof MidLine) {
|
|
3263
|
+
this.mid = line.mid;
|
|
3264
|
+
return true;
|
|
3265
|
+
}
|
|
3266
|
+
if (line instanceof FingerprintLine) {
|
|
3267
|
+
this.fingerprint = line.fingerprint;
|
|
3268
|
+
return true;
|
|
3269
|
+
}
|
|
3270
|
+
if (line instanceof SetupLine) {
|
|
3271
|
+
this.setup = line.setup;
|
|
3272
|
+
return true;
|
|
3273
|
+
}
|
|
3274
|
+
if (line instanceof ConnectionLine) {
|
|
3275
|
+
this.connection = line;
|
|
3276
|
+
return true;
|
|
3277
|
+
}
|
|
3278
|
+
if (line instanceof ContentLine) {
|
|
3279
|
+
this.content = line;
|
|
3280
|
+
return true;
|
|
3281
|
+
}
|
|
3282
|
+
return this.iceInfo.addLine(line);
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3183
3285
|
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3286
|
+
class ApplicationMediaDescription extends MediaDescription {
|
|
3287
|
+
constructor(mediaLine) {
|
|
3288
|
+
super(mediaLine.type, mediaLine.port, mediaLine.protocol);
|
|
3289
|
+
this.fmts = [];
|
|
3290
|
+
this.fmts = mediaLine.formats;
|
|
3291
|
+
}
|
|
3292
|
+
toLines() {
|
|
3293
|
+
const lines = [];
|
|
3294
|
+
lines.push(new MediaLine(this.type, this.port, this.protocol, this.fmts));
|
|
3295
|
+
if (this.connection) {
|
|
3296
|
+
lines.push(this.connection);
|
|
3297
|
+
}
|
|
3298
|
+
if (this.bandwidth) {
|
|
3299
|
+
lines.push(this.bandwidth);
|
|
3300
|
+
}
|
|
3301
|
+
lines.push(...this.iceInfo.toLines());
|
|
3302
|
+
if (this.fingerprint) {
|
|
3303
|
+
lines.push(new FingerprintLine(this.fingerprint));
|
|
3304
|
+
}
|
|
3305
|
+
if (this.setup) {
|
|
3306
|
+
lines.push(new SetupLine(this.setup));
|
|
3307
|
+
}
|
|
3308
|
+
if (this.mid) {
|
|
3309
|
+
lines.push(new MidLine(this.mid));
|
|
3310
|
+
}
|
|
3311
|
+
if (this.content) {
|
|
3312
|
+
lines.push(this.content);
|
|
3313
|
+
}
|
|
3314
|
+
if (this.sctpPort) {
|
|
3315
|
+
lines.push(new SctpPortLine(this.sctpPort));
|
|
3316
|
+
}
|
|
3317
|
+
if (this.maxMessageSize) {
|
|
3318
|
+
lines.push(new MaxMessageSizeLine(this.maxMessageSize));
|
|
3319
|
+
}
|
|
3320
|
+
lines.push(...this.otherLines);
|
|
3321
|
+
return lines;
|
|
3322
|
+
}
|
|
3323
|
+
addLine(line) {
|
|
3324
|
+
if (super.addLine(line)) {
|
|
3325
|
+
return true;
|
|
3326
|
+
}
|
|
3327
|
+
if (line instanceof MediaLine) {
|
|
3328
|
+
throw new Error('Error: tried passing a MediaLine to an existing MediaInfo');
|
|
3329
|
+
}
|
|
3330
|
+
if (line instanceof SctpPortLine) {
|
|
3331
|
+
this.sctpPort = line.port;
|
|
3332
|
+
return true;
|
|
3333
|
+
}
|
|
3334
|
+
if (line instanceof MaxMessageSizeLine) {
|
|
3335
|
+
this.maxMessageSize = line.maxMessageSize;
|
|
3336
|
+
return true;
|
|
3337
|
+
}
|
|
3338
|
+
this.otherLines.push(line);
|
|
3339
|
+
return true;
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3197
3342
|
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3343
|
+
class CodecInfo {
|
|
3344
|
+
constructor(pt) {
|
|
3345
|
+
this.fmtParams = [];
|
|
3346
|
+
this.feedback = [];
|
|
3347
|
+
this.pt = pt;
|
|
3348
|
+
}
|
|
3349
|
+
addLine(line) {
|
|
3350
|
+
if (line instanceof RtpMapLine) {
|
|
3351
|
+
this.name = line.encodingName;
|
|
3352
|
+
this.clockRate = line.clockRate;
|
|
3353
|
+
this.encodingParams = line.encodingParams;
|
|
3354
|
+
return true;
|
|
3355
|
+
}
|
|
3356
|
+
if (line instanceof FmtpLine) {
|
|
3357
|
+
this.fmtParams.push(line.params);
|
|
3358
|
+
if (line.params.indexOf('apt') !== -1) {
|
|
3359
|
+
const apt = line.params.split('=')[1];
|
|
3360
|
+
this.primaryCodecPt = parseInt(apt, 10);
|
|
3361
|
+
}
|
|
3362
|
+
return true;
|
|
3363
|
+
}
|
|
3364
|
+
if (line instanceof RtcpFbLine) {
|
|
3365
|
+
this.feedback.push(line.feedback);
|
|
3366
|
+
return true;
|
|
3367
|
+
}
|
|
3368
|
+
return false;
|
|
3369
|
+
}
|
|
3370
|
+
toLines() {
|
|
3371
|
+
const lines = [];
|
|
3372
|
+
lines.push(new RtpMapLine(this.pt, this.name, this.clockRate, this.encodingParams));
|
|
3373
|
+
this.feedback.forEach((fb) => {
|
|
3374
|
+
lines.push(new RtcpFbLine(this.pt, fb));
|
|
3375
|
+
});
|
|
3376
|
+
this.fmtParams.forEach((fmt) => {
|
|
3377
|
+
lines.push(new FmtpLine(this.pt, fmt));
|
|
3378
|
+
});
|
|
3379
|
+
return lines;
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3201
3382
|
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3383
|
+
class AvMediaDescription extends MediaDescription {
|
|
3384
|
+
constructor(mediaLine) {
|
|
3385
|
+
super(mediaLine.type, mediaLine.port, mediaLine.protocol);
|
|
3386
|
+
this.pts = [];
|
|
3387
|
+
this.extMaps = [];
|
|
3388
|
+
this.rids = [];
|
|
3389
|
+
this.codecs = new Map();
|
|
3390
|
+
this.rtcpMux = false;
|
|
3391
|
+
this.pts = mediaLine.formats.map((fmt) => {
|
|
3392
|
+
return parseInt(fmt, 10);
|
|
3393
|
+
});
|
|
3394
|
+
this.pts.forEach((pt) => this.codecs.set(pt, new CodecInfo(pt)));
|
|
3395
|
+
}
|
|
3396
|
+
toLines() {
|
|
3397
|
+
const lines = [];
|
|
3398
|
+
lines.push(new MediaLine(this.type, this.port, this.protocol, this.pts.map((pt) => `${pt}`)));
|
|
3399
|
+
if (this.connection) {
|
|
3400
|
+
lines.push(this.connection);
|
|
3401
|
+
}
|
|
3402
|
+
if (this.bandwidth) {
|
|
3403
|
+
lines.push(this.bandwidth);
|
|
3404
|
+
}
|
|
3405
|
+
lines.push(...this.iceInfo.toLines());
|
|
3406
|
+
if (this.fingerprint) {
|
|
3407
|
+
lines.push(new FingerprintLine(this.fingerprint));
|
|
3408
|
+
}
|
|
3409
|
+
if (this.setup) {
|
|
3410
|
+
lines.push(new SetupLine(this.setup));
|
|
3411
|
+
}
|
|
3412
|
+
if (this.mid) {
|
|
3413
|
+
lines.push(new MidLine(this.mid));
|
|
3414
|
+
}
|
|
3415
|
+
if (this.rtcpMux) {
|
|
3416
|
+
lines.push(new RtcpMuxLine());
|
|
3417
|
+
}
|
|
3418
|
+
if (this.content) {
|
|
3419
|
+
lines.push(this.content);
|
|
3420
|
+
}
|
|
3421
|
+
this.extMaps.forEach((extMap) => lines.push(extMap));
|
|
3422
|
+
this.rids.forEach((rid) => lines.push(rid));
|
|
3423
|
+
if (this.simulcast) {
|
|
3424
|
+
lines.push(this.simulcast);
|
|
3425
|
+
}
|
|
3426
|
+
if (this.direction) {
|
|
3427
|
+
lines.push(new DirectionLine(this.direction));
|
|
3428
|
+
}
|
|
3429
|
+
this.codecs.forEach((codec) => lines.push(...codec.toLines()));
|
|
3430
|
+
lines.push(...this.otherLines);
|
|
3431
|
+
return lines;
|
|
3432
|
+
}
|
|
3433
|
+
addLine(line) {
|
|
3434
|
+
if (super.addLine(line)) {
|
|
3435
|
+
return true;
|
|
3436
|
+
}
|
|
3437
|
+
if (line instanceof MediaLine) {
|
|
3438
|
+
throw new Error('Error: tried passing a MediaLine to an existing MediaInfo');
|
|
3439
|
+
}
|
|
3440
|
+
if (line instanceof DirectionLine) {
|
|
3441
|
+
this.direction = line.direction;
|
|
3442
|
+
return true;
|
|
3443
|
+
}
|
|
3444
|
+
if (line instanceof ExtMapLine) {
|
|
3445
|
+
this.extMaps.push(line);
|
|
3446
|
+
return true;
|
|
3447
|
+
}
|
|
3448
|
+
if (line instanceof RidLine) {
|
|
3449
|
+
this.rids.push(line);
|
|
3450
|
+
return true;
|
|
3451
|
+
}
|
|
3452
|
+
if (line instanceof RtcpMuxLine) {
|
|
3453
|
+
this.rtcpMux = true;
|
|
3454
|
+
return true;
|
|
3455
|
+
}
|
|
3456
|
+
if (line instanceof SimulcastLine) {
|
|
3457
|
+
this.simulcast = line;
|
|
3458
|
+
return true;
|
|
3459
|
+
}
|
|
3460
|
+
if (line instanceof RtpMapLine || line instanceof FmtpLine || line instanceof RtcpFbLine) {
|
|
3461
|
+
const codec = this.codecs.get(line.payloadType);
|
|
3462
|
+
if (!codec) {
|
|
3463
|
+
throw new Error(`Error: got line for unknown codec: ${line.toSdpLine()}`);
|
|
3464
|
+
}
|
|
3465
|
+
codec.addLine(line);
|
|
3466
|
+
return true;
|
|
3467
|
+
}
|
|
3468
|
+
this.otherLines.push(line);
|
|
3469
|
+
return true;
|
|
3470
|
+
}
|
|
3471
|
+
getCodecByPt(pt) {
|
|
3472
|
+
return this.codecs.get(pt);
|
|
3473
|
+
}
|
|
3474
|
+
removePt(pt) {
|
|
3475
|
+
const associatedPts = [...this.codecs.values()]
|
|
3476
|
+
.filter((ci) => ci.primaryCodecPt === pt)
|
|
3477
|
+
.map((ci) => ci.pt);
|
|
3478
|
+
const allPtsToRemove = [pt, ...associatedPts];
|
|
3479
|
+
allPtsToRemove.forEach((ptToRemove) => {
|
|
3480
|
+
this.codecs.delete(ptToRemove);
|
|
3481
|
+
});
|
|
3482
|
+
this.pts = this.pts.filter((existingPt) => allPtsToRemove.indexOf(existingPt) === -1);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3215
3485
|
|
|
3216
|
-
|
|
3217
|
-
|
|
3486
|
+
class SessionDescription {
|
|
3487
|
+
constructor() {
|
|
3488
|
+
this.groups = [];
|
|
3489
|
+
this.otherLines = [];
|
|
3490
|
+
}
|
|
3491
|
+
addLine(line) {
|
|
3492
|
+
if (line instanceof VersionLine) {
|
|
3493
|
+
this.version = line;
|
|
3494
|
+
return true;
|
|
3495
|
+
}
|
|
3496
|
+
if (line instanceof OriginLine) {
|
|
3497
|
+
this.origin = line;
|
|
3498
|
+
return true;
|
|
3499
|
+
}
|
|
3500
|
+
if (line instanceof SessionNameLine) {
|
|
3501
|
+
this.sessionName = line;
|
|
3502
|
+
return true;
|
|
3503
|
+
}
|
|
3504
|
+
if (line instanceof SessionInformationLine) {
|
|
3505
|
+
this.information = line;
|
|
3506
|
+
return true;
|
|
3507
|
+
}
|
|
3508
|
+
if (line instanceof TimingLine) {
|
|
3509
|
+
this.timing = line;
|
|
3510
|
+
return true;
|
|
3511
|
+
}
|
|
3512
|
+
if (line instanceof ConnectionLine) {
|
|
3513
|
+
this.connection = line;
|
|
3514
|
+
return true;
|
|
3515
|
+
}
|
|
3516
|
+
if (line instanceof BandwidthLine) {
|
|
3517
|
+
this.bandwidth = line;
|
|
3518
|
+
return true;
|
|
3519
|
+
}
|
|
3520
|
+
if (line instanceof BundleGroupLine) {
|
|
3521
|
+
this.groups.push(line);
|
|
3522
|
+
return true;
|
|
3523
|
+
}
|
|
3524
|
+
this.otherLines.push(line);
|
|
3525
|
+
return true;
|
|
3526
|
+
}
|
|
3527
|
+
toLines() {
|
|
3528
|
+
const lines = [];
|
|
3529
|
+
if (this.version) {
|
|
3530
|
+
lines.push(this.version);
|
|
3531
|
+
}
|
|
3532
|
+
if (this.origin) {
|
|
3533
|
+
lines.push(this.origin);
|
|
3534
|
+
}
|
|
3535
|
+
if (this.sessionName) {
|
|
3536
|
+
lines.push(this.sessionName);
|
|
3537
|
+
}
|
|
3538
|
+
if (this.information) {
|
|
3539
|
+
lines.push(this.information);
|
|
3540
|
+
}
|
|
3541
|
+
if (this.connection) {
|
|
3542
|
+
lines.push(this.connection);
|
|
3543
|
+
}
|
|
3544
|
+
if (this.bandwidth) {
|
|
3545
|
+
lines.push(this.bandwidth);
|
|
3546
|
+
}
|
|
3547
|
+
if (this.timing) {
|
|
3548
|
+
lines.push(this.timing);
|
|
3549
|
+
}
|
|
3550
|
+
if (this.groups) {
|
|
3551
|
+
lines.push(...this.groups);
|
|
3552
|
+
}
|
|
3553
|
+
lines.push(...this.otherLines);
|
|
3554
|
+
return lines;
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3218
3557
|
|
|
3219
|
-
|
|
3220
|
-
|
|
3558
|
+
class Sdp {
|
|
3559
|
+
constructor() {
|
|
3560
|
+
this.session = new SessionDescription();
|
|
3561
|
+
this.media = [];
|
|
3562
|
+
}
|
|
3563
|
+
get avMedia() {
|
|
3564
|
+
return this.media.filter((mi) => mi instanceof AvMediaDescription);
|
|
3565
|
+
}
|
|
3566
|
+
toString() {
|
|
3567
|
+
const lines = [];
|
|
3568
|
+
lines.push(...this.session.toLines());
|
|
3569
|
+
this.media.forEach((m) => lines.push(...m.toLines()));
|
|
3570
|
+
return `${lines.map((l) => l.toSdpLine()).join('\r\n')}\r\n`;
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3221
3573
|
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3574
|
+
class Grammar {
|
|
3575
|
+
constructor() {
|
|
3576
|
+
this.parsers = new Map();
|
|
3577
|
+
}
|
|
3578
|
+
addParser(lineType, parser) {
|
|
3579
|
+
const parsers = this.parsers.get(lineType) || [];
|
|
3580
|
+
parsers.push(parser);
|
|
3581
|
+
this.parsers.set(lineType, parsers);
|
|
3582
|
+
}
|
|
3583
|
+
getParsers(lineType) {
|
|
3584
|
+
return this.parsers.get(lineType) || [];
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
class SdpGrammar extends Grammar {
|
|
3588
|
+
constructor() {
|
|
3589
|
+
super();
|
|
3590
|
+
this.addParser('v', VersionLine.fromSdpLine);
|
|
3591
|
+
this.addParser('o', OriginLine.fromSdpLine);
|
|
3592
|
+
this.addParser('c', ConnectionLine.fromSdpLine);
|
|
3593
|
+
this.addParser('i', SessionInformationLine.fromSdpLine);
|
|
3594
|
+
this.addParser('m', MediaLine.fromSdpLine);
|
|
3595
|
+
this.addParser('s', SessionNameLine.fromSdpLine);
|
|
3596
|
+
this.addParser('t', TimingLine.fromSdpLine);
|
|
3597
|
+
this.addParser('b', BandwidthLine.fromSdpLine);
|
|
3598
|
+
this.addParser('a', RtpMapLine.fromSdpLine);
|
|
3599
|
+
this.addParser('a', RtcpFbLine.fromSdpLine);
|
|
3600
|
+
this.addParser('a', FmtpLine.fromSdpLine);
|
|
3601
|
+
this.addParser('a', DirectionLine.fromSdpLine);
|
|
3602
|
+
this.addParser('a', ExtMapLine.fromSdpLine);
|
|
3603
|
+
this.addParser('a', MidLine.fromSdpLine);
|
|
3604
|
+
this.addParser('a', IceUfragLine.fromSdpLine);
|
|
3605
|
+
this.addParser('a', IcePwdLine.fromSdpLine);
|
|
3606
|
+
this.addParser('a', IceOptionsLine.fromSdpLine);
|
|
3607
|
+
this.addParser('a', FingerprintLine.fromSdpLine);
|
|
3608
|
+
this.addParser('a', SetupLine.fromSdpLine);
|
|
3609
|
+
this.addParser('a', SctpPortLine.fromSdpLine);
|
|
3610
|
+
this.addParser('a', MaxMessageSizeLine.fromSdpLine);
|
|
3611
|
+
this.addParser('a', RtcpMuxLine.fromSdpLine);
|
|
3612
|
+
this.addParser('a', BundleGroupLine.fromSdpLine);
|
|
3613
|
+
this.addParser('a', ContentLine.fromSdpLine);
|
|
3614
|
+
this.addParser('a', RidLine.fromSdpLine);
|
|
3615
|
+
this.addParser('a', CandidateLine.fromSdpLine);
|
|
3616
|
+
this.addParser('a', SimulcastLine.fromSdpLine);
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
const DefaultSdpGrammar = new SdpGrammar();
|
|
3620
|
+
function isValidLine(line) {
|
|
3621
|
+
return line.length > 2;
|
|
3622
|
+
}
|
|
3623
|
+
function parseToModel(lines) {
|
|
3624
|
+
const sdp = new Sdp();
|
|
3625
|
+
let currBlock = sdp.session;
|
|
3626
|
+
lines.forEach((l) => {
|
|
3627
|
+
if (l instanceof MediaLine) {
|
|
3628
|
+
let mediaInfo;
|
|
3629
|
+
if (l.type === 'audio' || l.type === 'video') {
|
|
3630
|
+
mediaInfo = new AvMediaDescription(l);
|
|
3631
|
+
}
|
|
3632
|
+
else if (l.type === 'application') {
|
|
3633
|
+
mediaInfo = new ApplicationMediaDescription(l);
|
|
3634
|
+
}
|
|
3635
|
+
else {
|
|
3636
|
+
throw new Error(`Unhandled media type: ${l.type}`);
|
|
3637
|
+
}
|
|
3638
|
+
sdp.media.push(mediaInfo);
|
|
3639
|
+
currBlock = mediaInfo;
|
|
3640
|
+
}
|
|
3641
|
+
else {
|
|
3642
|
+
currBlock.addLine(l);
|
|
3643
|
+
}
|
|
3644
|
+
});
|
|
3645
|
+
return sdp;
|
|
3646
|
+
}
|
|
3647
|
+
function parseToLines(sdp, grammar) {
|
|
3648
|
+
const lines = [];
|
|
3649
|
+
sdp
|
|
3650
|
+
.split(/(\r\n|\r|\n)/)
|
|
3651
|
+
.filter(isValidLine)
|
|
3652
|
+
.forEach((l) => {
|
|
3653
|
+
const lineType = l[0];
|
|
3654
|
+
const lineValue = l.slice(2);
|
|
3655
|
+
const parsers = grammar.getParsers(lineType);
|
|
3656
|
+
for (const parser of parsers) {
|
|
3657
|
+
const result = parser(lineValue);
|
|
3658
|
+
if (result) {
|
|
3659
|
+
lines.push(result);
|
|
3660
|
+
return;
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
const result = UnknownLine.fromSdpLine(l);
|
|
3664
|
+
lines.push(result);
|
|
3665
|
+
});
|
|
3666
|
+
return lines;
|
|
3667
|
+
}
|
|
3668
|
+
function parse(sdp, grammar = DefaultSdpGrammar) {
|
|
3669
|
+
const lines = parseToLines(sdp, grammar);
|
|
3670
|
+
const parsed = parseToModel(lines);
|
|
3671
|
+
return parsed;
|
|
3672
|
+
}
|
|
3230
3673
|
|
|
3231
|
-
const SDP_CARRIAGE_RETURN = '\r\n';
|
|
3232
3674
|
function getLocalTrackInfo(kind, receive, localTrack) {
|
|
3233
3675
|
const direction = (() => {
|
|
3234
3676
|
const send = !!localTrack;
|
|
@@ -3242,13 +3684,21 @@ function getLocalTrackInfo(kind, receive, localTrack) {
|
|
|
3242
3684
|
})();
|
|
3243
3685
|
return { trackOrKind: localTrack || kind, direction };
|
|
3244
3686
|
}
|
|
3687
|
+
function hasH264Codec(mediaLine) {
|
|
3688
|
+
for (const codec of mediaLine.codecs.values()) {
|
|
3689
|
+
if (codec.name?.toUpperCase() === 'H264') {
|
|
3690
|
+
return true;
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
return false;
|
|
3694
|
+
}
|
|
3245
3695
|
function isSdpInvalid(options, errorLog, sdp) {
|
|
3246
3696
|
if (!sdp) {
|
|
3247
3697
|
return 'iceCandidate: SDP missing';
|
|
3248
3698
|
}
|
|
3249
|
-
const parsedSdp =
|
|
3250
|
-
for (const mediaLine of parsedSdp.
|
|
3251
|
-
if (!mediaLine.candidates
|
|
3699
|
+
const parsedSdp = parse(sdp);
|
|
3700
|
+
for (const mediaLine of parsedSdp.avMedia) {
|
|
3701
|
+
if (!mediaLine.iceInfo.candidates.length) {
|
|
3252
3702
|
errorLog('isSdpInvalid', `ice candidates missing for m-line with mid=${mediaLine.mid}`);
|
|
3253
3703
|
return 'isSdpInvalid: ice candidates missing';
|
|
3254
3704
|
}
|
|
@@ -3256,46 +3706,147 @@ function isSdpInvalid(options, errorLog, sdp) {
|
|
|
3256
3706
|
errorLog('isSdpInvalid', `Found invalid port number 0 at m-line with mid=${mediaLine.mid}`);
|
|
3257
3707
|
return 'isSdpInvalid: Found invalid port number 0';
|
|
3258
3708
|
}
|
|
3259
|
-
if (!mediaLine.
|
|
3709
|
+
if (!mediaLine.iceInfo.pwd || !mediaLine.iceInfo.ufrag) {
|
|
3260
3710
|
errorLog('isSdpInvalid', `ice ufrag and password not found for m-line with mid=${mediaLine.mid}`);
|
|
3261
3711
|
return 'isSdpInvalid: ice ufrag and password not found';
|
|
3262
3712
|
}
|
|
3713
|
+
if (options.requireH264 && mediaLine.type === 'video' && !hasH264Codec(mediaLine)) {
|
|
3714
|
+
errorLog('isSdpInvalid', `H264 codec is missing for video media description with mid=${mediaLine.mid}`);
|
|
3715
|
+
return 'isSdpInvalid: H264 codec is missing';
|
|
3716
|
+
}
|
|
3263
3717
|
}
|
|
3264
3718
|
return '';
|
|
3265
3719
|
}
|
|
3266
|
-
function
|
|
3267
|
-
|
|
3720
|
+
function convertCLineToIPv4(sdp) {
|
|
3721
|
+
const convertConnectionProp = (connection) => {
|
|
3722
|
+
if (connection?.addrType === 'IP6') {
|
|
3723
|
+
connection.addrType = 'IP4';
|
|
3724
|
+
connection.ipAddr = '0.0.0.0';
|
|
3725
|
+
}
|
|
3726
|
+
};
|
|
3727
|
+
convertConnectionProp(sdp.session.connection);
|
|
3728
|
+
sdp.media.forEach((media) => {
|
|
3729
|
+
convertConnectionProp(media.connection);
|
|
3730
|
+
});
|
|
3268
3731
|
}
|
|
3269
3732
|
function convertPort9to0(sdp) {
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
let n = 0;
|
|
3274
|
-
let pos = 0;
|
|
3275
|
-
while (pos >= 0) {
|
|
3276
|
-
pos = string.indexOf(subString, pos);
|
|
3277
|
-
if (pos >= 0) {
|
|
3278
|
-
n += 1;
|
|
3279
|
-
pos += subString.length;
|
|
3733
|
+
sdp.media.forEach((media) => {
|
|
3734
|
+
if (media.port === 9) {
|
|
3735
|
+
media.port = 0;
|
|
3280
3736
|
}
|
|
3281
|
-
}
|
|
3282
|
-
return n;
|
|
3737
|
+
});
|
|
3283
3738
|
}
|
|
3284
3739
|
function setContentSlides(sdp) {
|
|
3285
|
-
|
|
3286
|
-
|
|
3740
|
+
const videoMediaDescriptions = sdp.avMedia.filter((media) => media.type === 'video');
|
|
3741
|
+
if (videoMediaDescriptions.length === 2) {
|
|
3742
|
+
videoMediaDescriptions[1].addLine(new ContentLine(['slides']));
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
class AnyLine extends Line {
|
|
3746
|
+
value;
|
|
3747
|
+
constructor(value) {
|
|
3748
|
+
super();
|
|
3749
|
+
this.value = value;
|
|
3750
|
+
}
|
|
3751
|
+
static fromSdpLine() {
|
|
3752
|
+
return undefined;
|
|
3753
|
+
}
|
|
3754
|
+
toSdpLine() {
|
|
3755
|
+
return `a=${this.value}`;
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
function addBandwidthLimits(sdp, limits) {
|
|
3759
|
+
sdp.avMedia.forEach((media) => {
|
|
3760
|
+
if (media.type === 'audio') {
|
|
3761
|
+
media.addLine(new BandwidthLine('TIAS', limits.audio));
|
|
3762
|
+
}
|
|
3763
|
+
else if (media.type === 'video') {
|
|
3764
|
+
media.addLine(new BandwidthLine('TIAS', limits.video));
|
|
3765
|
+
}
|
|
3766
|
+
});
|
|
3767
|
+
}
|
|
3768
|
+
function addPeriodicKeyframes(sdp, value) {
|
|
3769
|
+
sdp.avMedia.forEach((media) => {
|
|
3770
|
+
if (media.type === 'video') {
|
|
3771
|
+
media.addLine(new AnyLine(`periodic-keyframes:${value}`));
|
|
3772
|
+
}
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
3775
|
+
function disableExtmap(sdp) {
|
|
3776
|
+
sdp.avMedia.forEach((media) => {
|
|
3777
|
+
media.extMaps.length = 0;
|
|
3778
|
+
});
|
|
3779
|
+
}
|
|
3780
|
+
function appendToH264fmtpParams(sdp, paramsToAppend) {
|
|
3781
|
+
sdp.avMedia.forEach((media) => {
|
|
3782
|
+
if (media.type === 'video') {
|
|
3783
|
+
media.codecs.forEach((codec) => {
|
|
3784
|
+
if (codec.name?.toUpperCase() === 'H264') {
|
|
3785
|
+
codec.fmtParams = codec.fmtParams.map((fmtp) => `${fmtp};${paramsToAppend}`);
|
|
3786
|
+
}
|
|
3787
|
+
});
|
|
3788
|
+
}
|
|
3789
|
+
});
|
|
3790
|
+
}
|
|
3791
|
+
function setH264MaxFs(sdp, maxFsValue) {
|
|
3792
|
+
appendToH264fmtpParams(sdp, `max-fs=${maxFsValue}`);
|
|
3793
|
+
}
|
|
3794
|
+
function disableRtx(sdp) {
|
|
3795
|
+
sdp.avMedia.forEach((media) => {
|
|
3796
|
+
const payloadTypesToRemove = [];
|
|
3797
|
+
media.codecs.forEach((codec, codecPt) => {
|
|
3798
|
+
if (codec.name === 'rtx' && codec.primaryCodecPt) {
|
|
3799
|
+
payloadTypesToRemove.push(codecPt);
|
|
3800
|
+
}
|
|
3801
|
+
});
|
|
3802
|
+
payloadTypesToRemove.forEach((pt) => media.codecs.delete(pt));
|
|
3803
|
+
media.pts = media.pts.filter((pt) => !payloadTypesToRemove.includes(pt));
|
|
3804
|
+
});
|
|
3805
|
+
}
|
|
3806
|
+
function mungeLocalSdpForBrowser(config, sdp) {
|
|
3807
|
+
const parsedSdp = parse(sdp);
|
|
3808
|
+
if (config.disableRtx) {
|
|
3809
|
+
disableRtx(parsedSdp);
|
|
3287
3810
|
}
|
|
3288
|
-
return
|
|
3811
|
+
return parsedSdp.toString();
|
|
3289
3812
|
}
|
|
3290
3813
|
function mungeLocalSdp(config, sdp) {
|
|
3291
|
-
|
|
3814
|
+
const parsedSdp = parse(sdp);
|
|
3815
|
+
if (config.convertCLineToIPv4) {
|
|
3816
|
+
convertCLineToIPv4(parsedSdp);
|
|
3817
|
+
}
|
|
3818
|
+
if (config.bandwidthLimits) {
|
|
3819
|
+
addBandwidthLimits(parsedSdp, config.bandwidthLimits);
|
|
3820
|
+
}
|
|
3821
|
+
if (config.periodicKeyframes) {
|
|
3822
|
+
addPeriodicKeyframes(parsedSdp, config.periodicKeyframes);
|
|
3823
|
+
}
|
|
3292
3824
|
if (config.convertPort9to0) {
|
|
3293
|
-
|
|
3825
|
+
convertPort9to0(parsedSdp);
|
|
3294
3826
|
}
|
|
3295
3827
|
if (config.addContentSlides) {
|
|
3296
|
-
|
|
3828
|
+
setContentSlides(parsedSdp);
|
|
3829
|
+
}
|
|
3830
|
+
if (config.disableExtmap) {
|
|
3831
|
+
disableExtmap(parsedSdp);
|
|
3832
|
+
}
|
|
3833
|
+
if (config.h264MaxFs) {
|
|
3834
|
+
setH264MaxFs(parsedSdp, config.h264MaxFs);
|
|
3835
|
+
}
|
|
3836
|
+
return parsedSdp.toString();
|
|
3837
|
+
}
|
|
3838
|
+
function setStartBitrate(sdp, startBitrate) {
|
|
3839
|
+
appendToH264fmtpParams(sdp, `x-google-start-bitrate=${startBitrate}`);
|
|
3840
|
+
}
|
|
3841
|
+
function mungeRemoteSdp(config, sdp) {
|
|
3842
|
+
const parsedSdp = parse(sdp);
|
|
3843
|
+
if (config.startBitrate) {
|
|
3844
|
+
setStartBitrate(parsedSdp, config.startBitrate);
|
|
3297
3845
|
}
|
|
3298
|
-
|
|
3846
|
+
if (config.disableExtmap) {
|
|
3847
|
+
disableExtmap(parsedSdp);
|
|
3848
|
+
}
|
|
3849
|
+
return parsedSdp.toString();
|
|
3299
3850
|
}
|
|
3300
3851
|
|
|
3301
3852
|
var Event$1;
|
|
@@ -3600,11 +4151,15 @@ class MediaConnection$1 extends EventEmitter {
|
|
|
3600
4151
|
.createOffer()
|
|
3601
4152
|
.then((description) => {
|
|
3602
4153
|
this.log('createLocalOffer', 'local SDP offer created');
|
|
3603
|
-
|
|
4154
|
+
const mungedDescription = {
|
|
4155
|
+
type: description.type,
|
|
4156
|
+
sdp: mungeLocalSdpForBrowser(this.config.sdpMunging, description?.sdp || ''),
|
|
4157
|
+
};
|
|
4158
|
+
return this.pc.setLocalDescription(mungedDescription);
|
|
3604
4159
|
})
|
|
3605
4160
|
.then(() => this.waitForIceCandidates())
|
|
3606
4161
|
.then(() => {
|
|
3607
|
-
const mungedSdp = mungeLocalSdp(this.config.sdpMunging, this.pc.localDescription
|
|
4162
|
+
const mungedSdp = mungeLocalSdp(this.config.sdpMunging, this.pc.localDescription?.sdp || '');
|
|
3608
4163
|
return { sdp: mungedSdp };
|
|
3609
4164
|
});
|
|
3610
4165
|
}
|
|
@@ -3613,17 +4168,24 @@ class MediaConnection$1 extends EventEmitter {
|
|
|
3613
4168
|
if (!sdp) {
|
|
3614
4169
|
return Promise.reject(new Error('SDP missing'));
|
|
3615
4170
|
}
|
|
4171
|
+
const mungedRemoteSdp = mungeRemoteSdp(this.config.sdpMunging, sdp);
|
|
3616
4172
|
return this.pc
|
|
3617
4173
|
.setRemoteDescription(new window.RTCSessionDescription({
|
|
3618
4174
|
type: 'offer',
|
|
3619
|
-
sdp,
|
|
4175
|
+
sdp: mungedRemoteSdp,
|
|
3620
4176
|
}))
|
|
3621
4177
|
.then(() => this.pc.createAnswer())
|
|
3622
|
-
.then((answer) =>
|
|
4178
|
+
.then((answer) => {
|
|
4179
|
+
const mungedAnswer = {
|
|
4180
|
+
type: answer.type,
|
|
4181
|
+
sdp: mungeLocalSdpForBrowser(this.config.sdpMunging, answer?.sdp || ''),
|
|
4182
|
+
};
|
|
4183
|
+
return this.pc.setLocalDescription(mungedAnswer);
|
|
4184
|
+
})
|
|
3623
4185
|
.then(() => this.waitForIceCandidates())
|
|
3624
4186
|
.then(() => {
|
|
3625
|
-
const
|
|
3626
|
-
return { sdp:
|
|
4187
|
+
const mungedLocalSdp = mungeLocalSdp(this.config.sdpMunging, this.pc.localDescription?.sdp || '');
|
|
4188
|
+
return { sdp: mungedLocalSdp };
|
|
3627
4189
|
});
|
|
3628
4190
|
}
|
|
3629
4191
|
handleRemoteAnswer(sdp) {
|
|
@@ -3631,9 +4193,10 @@ class MediaConnection$1 extends EventEmitter {
|
|
|
3631
4193
|
if (!sdp) {
|
|
3632
4194
|
return Promise.reject(new Error('SDP missing'));
|
|
3633
4195
|
}
|
|
4196
|
+
const mungedRemoteSdp = mungeRemoteSdp(this.config.sdpMunging, sdp);
|
|
3634
4197
|
return this.pc.setRemoteDescription(new window.RTCSessionDescription({
|
|
3635
4198
|
type: 'answer',
|
|
3636
|
-
sdp,
|
|
4199
|
+
sdp: mungedRemoteSdp,
|
|
3637
4200
|
}));
|
|
3638
4201
|
}
|
|
3639
4202
|
waitForIceCandidates() {
|
|
@@ -3642,6 +4205,7 @@ class MediaConnection$1 extends EventEmitter {
|
|
|
3642
4205
|
let done = false;
|
|
3643
4206
|
const isLocalSdpValid = () => !isSdpInvalid({
|
|
3644
4207
|
allowPort0: !!this.config.sdpMunging.convertPort9to0,
|
|
4208
|
+
requireH264: !!this.config.requireH264,
|
|
3645
4209
|
}, this.error.bind(this), this.pc.localDescription?.sdp);
|
|
3646
4210
|
const doneGatheringIceCandidates = () => {
|
|
3647
4211
|
if (!done) {
|
|
@@ -3662,6 +4226,7 @@ class MediaConnection$1 extends EventEmitter {
|
|
|
3662
4226
|
if (this.pc.iceGatheringState === 'complete' && isLocalSdpValid()) {
|
|
3663
4227
|
this.log('waitForIceCandidates()', 'iceGatheringState is already "complete" and local SDP is valid');
|
|
3664
4228
|
resolve();
|
|
4229
|
+
return;
|
|
3665
4230
|
}
|
|
3666
4231
|
this.log('waitForIceCandidates()', 'waiting for ICE candidates to be gathered...');
|
|
3667
4232
|
this.pc.onicegatheringstatechange = () => {
|
|
@@ -12524,6 +13089,19 @@ async function enableBNR(track) {
|
|
|
12524
13089
|
action: 'enableBNR()',
|
|
12525
13090
|
description: 'BNR module is present already',
|
|
12526
13091
|
});
|
|
13092
|
+
const oldDestinationTrack = bnrProcessor.destinationTrack;
|
|
13093
|
+
if (track.id === oldDestinationTrack.id) {
|
|
13094
|
+
const oldTrackErrorMsg = 'BNR is enabled on the track already';
|
|
13095
|
+
const oldTrackError = new Error(oldTrackErrorMsg);
|
|
13096
|
+
logger.error({
|
|
13097
|
+
ID: track.id,
|
|
13098
|
+
mediaType: MEDIA_STREAM_TRACK,
|
|
13099
|
+
action: 'enableBNR()',
|
|
13100
|
+
description: oldTrackErrorMsg,
|
|
13101
|
+
error: oldTrackError,
|
|
13102
|
+
});
|
|
13103
|
+
throw oldTrackError;
|
|
13104
|
+
}
|
|
12527
13105
|
logger.info({
|
|
12528
13106
|
ID: track.id,
|
|
12529
13107
|
mediaType: MEDIA_STREAM_TRACK,
|
|
@@ -12552,6 +13130,7 @@ async function enableBNR(track) {
|
|
|
12552
13130
|
});
|
|
12553
13131
|
const destinationStream = bnrProcessor.destinationStream.stream;
|
|
12554
13132
|
const [destinationTrack] = destinationStream.getAudioTracks();
|
|
13133
|
+
bnrProcessor.destinationTrack = destinationTrack;
|
|
12555
13134
|
return destinationTrack;
|
|
12556
13135
|
}
|
|
12557
13136
|
catch (error) {
|
|
@@ -12609,6 +13188,7 @@ function disableBNR() {
|
|
|
12609
13188
|
delete bnrProcessor.audioContext;
|
|
12610
13189
|
delete bnrProcessor.sourceNode;
|
|
12611
13190
|
delete bnrProcessor.destinationStream;
|
|
13191
|
+
delete bnrProcessor.destinationTrack;
|
|
12612
13192
|
return track;
|
|
12613
13193
|
}
|
|
12614
13194
|
catch (error) {
|