@webex/internal-media-core 0.0.2-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.
Files changed (124) hide show
  1. package/dist/cjs/index.js +13246 -0
  2. package/dist/esm/index.js +1342 -762
  3. package/dist/types/Media/Effects/BNR/Bnr.d.ts.map +1 -1
  4. package/dist/types/Media/Effects/BNR/BnrMock.d.ts.map +1 -1
  5. package/dist/types/MediaConnection/MediaConnection.d.ts.map +1 -1
  6. package/dist/types/MediaConnection/config.d.ts +11 -0
  7. package/dist/types/MediaConnection/config.d.ts.map +1 -1
  8. package/dist/types/MediaConnection/logger.d.ts +1 -1
  9. package/dist/types/MediaConnection/logger.d.ts.map +1 -1
  10. package/dist/types/MediaConnection/utils.d.ts +3 -0
  11. package/dist/types/MediaConnection/utils.d.ts.map +1 -1
  12. package/dist/types/MediaConnection/utils.test-fixtures.d.ts +10 -0
  13. package/dist/types/MediaConnection/utils.test-fixtures.d.ts.map +1 -1
  14. package/package.json +13 -8
  15. package/dist/transpiled/Logger/index.js +0 -41
  16. package/dist/transpiled/Logger/index.js.map +0 -1
  17. package/dist/transpiled/Media/Device/Device.js +0 -21
  18. package/dist/transpiled/Media/Device/Device.js.map +0 -1
  19. package/dist/transpiled/Media/Device/DeviceMocks.js +0 -65
  20. package/dist/transpiled/Media/Device/DeviceMocks.js.map +0 -1
  21. package/dist/transpiled/Media/Device/index.js +0 -2
  22. package/dist/transpiled/Media/Device/index.js.map +0 -1
  23. package/dist/transpiled/Media/Effects/BNR/Bnr.integration-test.js +0 -47
  24. package/dist/transpiled/Media/Effects/BNR/Bnr.integration-test.js.map +0 -1
  25. package/dist/transpiled/Media/Effects/BNR/Bnr.js +0 -187
  26. package/dist/transpiled/Media/Effects/BNR/Bnr.js.map +0 -1
  27. package/dist/transpiled/Media/Effects/BNR/Bnr.test.js +0 -37
  28. package/dist/transpiled/Media/Effects/BNR/Bnr.test.js.map +0 -1
  29. package/dist/transpiled/Media/Effects/BNR/BnrMock.js +0 -92
  30. package/dist/transpiled/Media/Effects/BNR/BnrMock.js.map +0 -1
  31. package/dist/transpiled/Media/Effects/BNR/index.js +0 -2
  32. package/dist/transpiled/Media/Effects/BNR/index.js.map +0 -1
  33. package/dist/transpiled/Media/Media.integration-test.js +0 -40
  34. package/dist/transpiled/Media/Media.integration-test.js.map +0 -1
  35. package/dist/transpiled/Media/Media.test.js +0 -291
  36. package/dist/transpiled/Media/Media.test.js.map +0 -1
  37. package/dist/transpiled/Media/Track/BufferSourceAudioTrack.js +0 -4
  38. package/dist/transpiled/Media/Track/BufferSourceAudioTrack.js.map +0 -1
  39. package/dist/transpiled/Media/Track/CameraVideoTrack.js +0 -4
  40. package/dist/transpiled/Media/Track/CameraVideoTrack.js.map +0 -1
  41. package/dist/transpiled/Media/Track/LocalAudioTrack.js +0 -4
  42. package/dist/transpiled/Media/Track/LocalAudioTrack.js.map +0 -1
  43. package/dist/transpiled/Media/Track/LocalTrack.js +0 -4
  44. package/dist/transpiled/Media/Track/LocalTrack.js.map +0 -1
  45. package/dist/transpiled/Media/Track/LocalVideoTrack.js +0 -4
  46. package/dist/transpiled/Media/Track/LocalVideoTrack.js.map +0 -1
  47. package/dist/transpiled/Media/Track/MicrophoneAudioTrack.js +0 -4
  48. package/dist/transpiled/Media/Track/MicrophoneAudioTrack.js.map +0 -1
  49. package/dist/transpiled/Media/Track/RemoteAudioTrack.js +0 -4
  50. package/dist/transpiled/Media/Track/RemoteAudioTrack.js.map +0 -1
  51. package/dist/transpiled/Media/Track/RemoteTrack.js +0 -4
  52. package/dist/transpiled/Media/Track/RemoteTrack.js.map +0 -1
  53. package/dist/transpiled/Media/Track/RemoteVideoTrack.js +0 -4
  54. package/dist/transpiled/Media/Track/RemoteVideoTrack.js.map +0 -1
  55. package/dist/transpiled/Media/Track/Track.integration-test.js +0 -118
  56. package/dist/transpiled/Media/Track/Track.integration-test.js.map +0 -1
  57. package/dist/transpiled/Media/Track/Track.js +0 -120
  58. package/dist/transpiled/Media/Track/Track.js.map +0 -1
  59. package/dist/transpiled/Media/Track/Track.test.js +0 -26
  60. package/dist/transpiled/Media/Track/Track.test.js.map +0 -1
  61. package/dist/transpiled/Media/Track/TrackMock.js +0 -109
  62. package/dist/transpiled/Media/Track/TrackMock.js.map +0 -1
  63. package/dist/transpiled/Media/Track/Utils.js +0 -31
  64. package/dist/transpiled/Media/Track/Utils.js.map +0 -1
  65. package/dist/transpiled/Media/Track/index.js +0 -2
  66. package/dist/transpiled/Media/Track/index.js.map +0 -1
  67. package/dist/transpiled/Media/index.js +0 -401
  68. package/dist/transpiled/Media/index.js.map +0 -1
  69. package/dist/transpiled/MediaConnection/EventEmitter.js +0 -4
  70. package/dist/transpiled/MediaConnection/EventEmitter.js.map +0 -1
  71. package/dist/transpiled/MediaConnection/MediaConnection.integration-test.js +0 -218
  72. package/dist/transpiled/MediaConnection/MediaConnection.integration-test.js.map +0 -1
  73. package/dist/transpiled/MediaConnection/MediaConnection.js +0 -357
  74. package/dist/transpiled/MediaConnection/MediaConnection.js.map +0 -1
  75. package/dist/transpiled/MediaConnection/MediaConnection.test.js +0 -427
  76. package/dist/transpiled/MediaConnection/MediaConnection.test.js.map +0 -1
  77. package/dist/transpiled/MediaConnection/RoapMediaConnection.integration-test.js +0 -368
  78. package/dist/transpiled/MediaConnection/RoapMediaConnection.integration-test.js.map +0 -1
  79. package/dist/transpiled/MediaConnection/RoapMediaConnection.js +0 -148
  80. package/dist/transpiled/MediaConnection/RoapMediaConnection.js.map +0 -1
  81. package/dist/transpiled/MediaConnection/RoapMediaConnection.test.js +0 -320
  82. package/dist/transpiled/MediaConnection/RoapMediaConnection.test.js.map +0 -1
  83. package/dist/transpiled/MediaConnection/config.js +0 -2
  84. package/dist/transpiled/MediaConnection/config.js.map +0 -1
  85. package/dist/transpiled/MediaConnection/eventTypes.js +0 -36
  86. package/dist/transpiled/MediaConnection/eventTypes.js.map +0 -1
  87. package/dist/transpiled/MediaConnection/index.js +0 -4
  88. package/dist/transpiled/MediaConnection/index.js.map +0 -1
  89. package/dist/transpiled/MediaConnection/logger.js +0 -22
  90. package/dist/transpiled/MediaConnection/logger.js.map +0 -1
  91. package/dist/transpiled/MediaConnection/roap.js +0 -399
  92. package/dist/transpiled/MediaConnection/roap.js.map +0 -1
  93. package/dist/transpiled/MediaConnection/roap.test.js +0 -873
  94. package/dist/transpiled/MediaConnection/roap.test.js.map +0 -1
  95. package/dist/transpiled/MediaConnection/roap.typegen.js +0 -2
  96. package/dist/transpiled/MediaConnection/roap.typegen.js.map +0 -1
  97. package/dist/transpiled/MediaConnection/testUtils/EventListener.js +0 -102
  98. package/dist/transpiled/MediaConnection/testUtils/EventListener.js.map +0 -1
  99. package/dist/transpiled/MediaConnection/testUtils/RoapListener.js +0 -15
  100. package/dist/transpiled/MediaConnection/testUtils/RoapListener.js.map +0 -1
  101. package/dist/transpiled/MediaConnection/testUtils/index.js +0 -17
  102. package/dist/transpiled/MediaConnection/testUtils/index.js.map +0 -1
  103. package/dist/transpiled/MediaConnection/testUtils/logger.js +0 -31
  104. package/dist/transpiled/MediaConnection/testUtils/logger.js.map +0 -1
  105. package/dist/transpiled/MediaConnection/testUtils.js +0 -14
  106. package/dist/transpiled/MediaConnection/testUtils.js.map +0 -1
  107. package/dist/transpiled/MediaConnection/utils.js +0 -71
  108. package/dist/transpiled/MediaConnection/utils.js.map +0 -1
  109. package/dist/transpiled/MediaConnection/utils.test-fixtures.js +0 -287
  110. package/dist/transpiled/MediaConnection/utils.test-fixtures.js.map +0 -1
  111. package/dist/transpiled/MediaConnection/utils.test.js +0 -20
  112. package/dist/transpiled/MediaConnection/utils.test.js.map +0 -1
  113. package/dist/transpiled/common/peerConnectionMock.js +0 -52
  114. package/dist/transpiled/common/peerConnectionMock.js.map +0 -1
  115. package/dist/transpiled/constants.js +0 -9
  116. package/dist/transpiled/constants.js.map +0 -1
  117. package/dist/transpiled/index.intergation-test.js +0 -14
  118. package/dist/transpiled/index.intergation-test.js.map +0 -1
  119. package/dist/transpiled/index.js +0 -41
  120. package/dist/transpiled/index.js.map +0 -1
  121. package/dist/types/MediaConnection/MediaConnection.integration-test.d.ts +0 -2
  122. package/dist/types/MediaConnection/MediaConnection.integration-test.d.ts.map +0 -1
  123. package/dist/types/MediaConnection/testUtils.d.ts +0 -7
  124. 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
- var lib = {};
2477
-
2478
- var parser$1 = {};
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
- str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v';
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
- // parse lines we understand
3023
- sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
3024
- var type = l[0];
3025
- var content = l.slice(2);
3026
- if (type === 'm') {
3027
- media.push({rtp: [], fmtp: []});
3028
- location = media[media.length-1]; // point at latest media line
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
- for (var j = 0; j < (grammar[type] || []).length; j += 1) {
3032
- var obj = grammar[type][j];
3033
- if (obj.reg.test(content)) {
3034
- return parseReg(obj, location, content);
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
- session.media = media; // link it up
3040
- return session;
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
- var paramReducer = function (acc, expr) {
3044
- var s = expr.split(/=(.+)/, 2);
3045
- if (s.length === 2) {
3046
- acc[s[0]] = toIntIfInt(s[1]);
3047
- } else if (s.length === 1 && expr.length > 1) {
3048
- acc[s[0]] = undefined;
3049
- }
3050
- return acc;
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
- exports.parseParams = function (str) {
3054
- return str.split(/;\s?/).reduce(paramReducer, {});
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
- // For backward compatibility - alias will be removed in 3.0.0
3058
- exports.parseFmtpConfig = exports.parseParams;
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
- exports.parsePayloads = function (str) {
3061
- return str.toString().split(' ').map(Number);
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
- exports.parseRemoteCandidates = function (str) {
3065
- var candidates = [];
3066
- var parts = str.split(' ').map(toIntIfInt);
3067
- for (var i = 0; i < parts.length; i += 3) {
3068
- candidates.push({
3069
- component: parts[i],
3070
- ip: parts[i + 1],
3071
- port: parts[i + 2]
3072
- });
3073
- }
3074
- return candidates;
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
- exports.parseImageAttributes = function (str) {
3078
- return str.split(' ').map(function (item) {
3079
- return item.substring(1, item.length-1).split(',').reduce(paramReducer, {});
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
- exports.parseSimulcastStreamList = function (str) {
3084
- return str.split(';').map(function (stream) {
3085
- return stream.split(',').map(function (format) {
3086
- var scid, paused = false;
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
- if (format[0] !== '~') {
3089
- scid = toIntIfInt(format);
3090
- } else {
3091
- scid = toIntIfInt(format.substring(1, format.length));
3092
- paused = true;
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
- return {
3096
- scid: scid,
3097
- paused: paused
3098
- };
3099
- });
3100
- });
3101
- };
3102
- }(parser$1));
3103
-
3104
- var grammar = grammar$2.exports;
3105
-
3106
- // customized util.format - discards excess arguments and can void middle ones
3107
- var formatRegExp = /%[sdv%]/g;
3108
- var format = function (formatStr) {
3109
- var i = 1;
3110
- var args = arguments;
3111
- var len = args.length;
3112
- return formatStr.replace(formatRegExp, function (x) {
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
- var makeLine = function (type, obj, location) {
3133
- var str = obj.format instanceof Function ?
3134
- (obj.format(obj.push ? location : location[obj.name])) :
3135
- obj.format;
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
- var args = [type + '=' + str];
3138
- if (obj.names) {
3139
- for (var i = 0; i < obj.names.length; i += 1) {
3140
- var n = obj.names[i];
3141
- if (obj.name) {
3142
- args.push(location[obj.name][n]);
3143
- }
3144
- else { // for mLine and push attributes
3145
- args.push(location[obj.names[i]]);
3146
- }
3147
- }
3148
- }
3149
- else {
3150
- args.push(location[obj.name]);
3151
- }
3152
- return format.apply(null, args);
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
- // RFC specified order
3156
- // TODO: extend this with all the rest
3157
- var defaultOuterOrder = [
3158
- 'v', 'o', 's', 'i',
3159
- 'u', 'e', 'p', 'c',
3160
- 'b', 't', 'r', 'z', 'a'
3161
- ];
3162
- var defaultInnerOrder = ['i', 'c', 'b', 'a'];
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
- var writer$1 = function (session, opts) {
3166
- opts = opts || {};
3167
- // ensure certain properties exist
3168
- if (session.version == null) {
3169
- session.version = 0; // 'v=0' must be there (only defined version atm)
3170
- }
3171
- if (session.name == null) {
3172
- session.name = ' '; // 's= ' must be there if no meaningful name set
3173
- }
3174
- session.media.forEach(function (mLine) {
3175
- if (mLine.payloads == null) {
3176
- mLine.payloads = '';
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
- var outerOrder = opts.outerOrder || defaultOuterOrder;
3181
- var innerOrder = opts.innerOrder || defaultInnerOrder;
3182
- var sdp = [];
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
- // loop through outerOrder for matching properties on session
3185
- outerOrder.forEach(function (type) {
3186
- grammar[type].forEach(function (obj) {
3187
- if (obj.name in session && session[obj.name] != null) {
3188
- sdp.push(makeLine(type, obj, session));
3189
- }
3190
- else if (obj.push in session && session[obj.push] != null) {
3191
- session[obj.push].forEach(function (el) {
3192
- sdp.push(makeLine(type, obj, el));
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
- // then for each media line, follow the innerOrder
3199
- session.media.forEach(function (mLine) {
3200
- sdp.push(makeLine('m', grammar.m[0], mLine));
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
- innerOrder.forEach(function (type) {
3203
- grammar[type].forEach(function (obj) {
3204
- if (obj.name in mLine && mLine[obj.name] != null) {
3205
- sdp.push(makeLine(type, obj, mLine));
3206
- }
3207
- else if (obj.push in mLine && mLine[obj.push] != null) {
3208
- mLine[obj.push].forEach(function (el) {
3209
- sdp.push(makeLine(type, obj, el));
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
- return sdp.join('\r\n') + '\r\n';
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
- var parser = parser$1;
3220
- var writer = writer$1;
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
- lib.write = writer;
3223
- lib.parse = parser.parse;
3224
- lib.parseParams = parser.parseParams;
3225
- lib.parseFmtpConfig = parser.parseFmtpConfig; // Alias of parseParams().
3226
- lib.parsePayloads = parser.parsePayloads;
3227
- lib.parseRemoteCandidates = parser.parseRemoteCandidates;
3228
- lib.parseImageAttributes = parser.parseImageAttributes;
3229
- lib.parseSimulcastStreamList = parser.parseSimulcastStreamList;
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 = lib.parse(sdp);
3250
- for (const mediaLine of parsedSdp.media) {
3251
- if (!mediaLine.candidates || mediaLine.candidates?.length === 0) {
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.icePwd || !mediaLine.iceUfrag) {
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 convertCLineToIpv4(sdp) {
3267
- return sdp.replace(/c=IN IP6 .*/gi, 'c=IN IP4 0.0.0.0');
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
- return sdp.replace(/^m=(audio|video) 9 /gim, 'm=$1 0 ');
3271
- }
3272
- function getNumOfOccurences(string, subString) {
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
- if (getNumOfOccurences(sdp, 'm=video ') === 2) {
3286
- return `${sdp}a=content:slides${SDP_CARRIAGE_RETURN}`;
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 sdp;
3811
+ return parsedSdp.toString();
3289
3812
  }
3290
3813
  function mungeLocalSdp(config, sdp) {
3291
- let mungedSdp = convertCLineToIpv4(sdp);
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
- mungedSdp = convertPort9to0(mungedSdp);
3825
+ convertPort9to0(parsedSdp);
3294
3826
  }
3295
3827
  if (config.addContentSlides) {
3296
- mungedSdp = setContentSlides(mungedSdp);
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
- return mungedSdp;
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
- return this.pc.setLocalDescription(description);
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.sdp);
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) => this.pc.setLocalDescription(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 mungedSdp = mungeLocalSdp(this.config.sdpMunging, this.pc.localDescription.sdp);
3626
- return { sdp: mungedSdp };
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) {