@webex/web-client-media-engine 2.0.4 → 2.0.6

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 CHANGED
@@ -5134,41 +5134,6 @@ class PeerConnection extends EventEmitter$2 {
5134
5134
  }
5135
5135
  PeerConnection.Events = PeerConnectionEvents;
5136
5136
 
5137
- /**
5138
- * Wait until the given peer connection has finished gathering ICE candidates and, when it has,
5139
- * return the local description with the candidates.
5140
- *
5141
- * @param peerConnection - The PeerConnection to use.
5142
- * @returns A Promise that resolves with the local description with the ICE candidates in it.
5143
- */
5144
- function getLocalDescriptionWithIceCandidates(peerConnection) {
5145
- return new Promise((resolve, reject) => {
5146
- /**
5147
- * A helper method to retrieve the local description and resolve, if one is found, or reject
5148
- * with an error if it's not.
5149
- */
5150
- const getLocalDescAndResolve = () => {
5151
- const localDesc = peerConnection.getLocalDescription();
5152
- if (localDesc) {
5153
- resolve(localDesc);
5154
- }
5155
- else {
5156
- reject(new Error('Local description was null'));
5157
- }
5158
- };
5159
- peerConnection.on(PeerConnection.Events.IceGatheringStateChange, (e) => {
5160
- if (e.target.iceGatheringState === 'complete') {
5161
- getLocalDescAndResolve();
5162
- }
5163
- // TODO(brian): throw an error if we see an error iceGatheringState
5164
- });
5165
- // It's possible ICE gathering is already done
5166
- if (peerConnection.iceGatheringState === 'complete') {
5167
- getLocalDescAndResolve();
5168
- }
5169
- });
5170
- }
5171
-
5172
5137
  exports.MediaCodecMimeType = void 0;
5173
5138
  (function (MediaCodecMimeType) {
5174
5139
  MediaCodecMimeType["H264"] = "video/H264";
@@ -9007,6 +8972,59 @@ class ReceiveOnlyTransceiver extends Transceiver {
9007
8972
  }
9008
8973
  ReceiveOnlyTransceiver.rid = '1';
9009
8974
 
8975
+ function deepCopy(source) {
8976
+ return Array.isArray(source)
8977
+ ? source.map((item) => deepCopy(item))
8978
+ : source instanceof Map
8979
+ ? new Map(source)
8980
+ : source instanceof Date
8981
+ ? new Date(source.getTime())
8982
+ : source && typeof source === 'object'
8983
+ ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
8984
+ Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop));
8985
+ o[prop] = deepCopy(source[prop]);
8986
+ return o;
8987
+ }, Object.create(Object.getPrototypeOf(source)))
8988
+ : source;
8989
+ }
8990
+
8991
+ function matchMlinesInAnswer(parsedOffer, parsedAnswer, streamSignalerManager) {
8992
+ parsedAnswer.session.groups = parsedOffer.session.groups;
8993
+ parsedAnswer.media = parsedOffer.media.map((offerMline) => {
8994
+ if (!offerMline.mid) {
8995
+ throw new Error(`Offer mline is missing MID`);
8996
+ }
8997
+ const answerMline = parsedAnswer.media.find((m) => m.mid === offerMline.mid);
8998
+ if (answerMline) {
8999
+ if (answerMline instanceof AvMediaDescription) {
9000
+ [...answerMline.codecs.values()].forEach((ci) => {
9001
+ ci.fmtParams.set('x-google-start-bitrate', '60000');
9002
+ });
9003
+ }
9004
+ return answerMline;
9005
+ }
9006
+ if (!(offerMline instanceof AvMediaDescription)) {
9007
+ throw new Error(`Answer is missing a non-media mline: ${offerMline.mid}`);
9008
+ }
9009
+ const startingMline = parsedAnswer.avMedia.find((m) => m.type === offerMline.type);
9010
+ if (!startingMline) {
9011
+ throw new Error(`Answer has no mline of type ${offerMline.type}, can't generate synthetic answer mline for mid ${offerMline.mid}`);
9012
+ }
9013
+ const fakeCorrespondingMline = deepCopy(startingMline);
9014
+ fakeCorrespondingMline.mid = offerMline.mid;
9015
+ fakeCorrespondingMline.simulcast = undefined;
9016
+ if (offerMline.direction === 'sendrecv' || offerMline.direction === 'sendonly') {
9017
+ fakeCorrespondingMline.direction = 'recvonly';
9018
+ }
9019
+ if (offerMline.direction === 'recvonly') {
9020
+ fakeCorrespondingMline.direction = 'sendonly';
9021
+ const ingressSignaler = streamSignalerManager.getIngressStreamSignalerOrThrow(offerMline.mid);
9022
+ ingressSignaler.signalRemoteStreams(fakeCorrespondingMline);
9023
+ }
9024
+ return fakeCorrespondingMline;
9025
+ });
9026
+ }
9027
+
9010
9028
  class JmpLine extends Line {
9011
9029
  constructor(versions) {
9012
9030
  super();
@@ -9171,6 +9189,15 @@ function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
9171
9189
  }
9172
9190
  });
9173
9191
  }
9192
+ function injectDummyCandidates(parsedSdp) {
9193
+ parsedSdp.media.forEach((mLine) => {
9194
+ if (mLine.iceInfo.candidates.length === 0) {
9195
+ mLine.addLine(new CandidateLine('dummy1', 1, 'udp', 1, '0.0.0.0', 1, 'host'));
9196
+ mLine.addLine(new CandidateLine('dummy2', 2, 'tcp', 2, '0.0.0.0', 2, 'host'));
9197
+ mLine.addLine(new CandidateLine('dummy3', 3, 'udp', 3, '0.0.0.0', 3, 'relay'));
9198
+ }
9199
+ });
9200
+ }
9174
9201
  function hasSimulcast(av) {
9175
9202
  return !!av.simulcast || av.ssrcGroups.map((sg) => sg.semantics).some((sem) => sem === 'SIM');
9176
9203
  }
@@ -13105,59 +13132,6 @@ function setLogHandler(logHandler) {
13105
13132
  Logger$2.setHandler(logHandler);
13106
13133
  }
13107
13134
 
13108
- function deepCopy(source) {
13109
- return Array.isArray(source)
13110
- ? source.map((item) => deepCopy(item))
13111
- : source instanceof Map
13112
- ? new Map(source)
13113
- : source instanceof Date
13114
- ? new Date(source.getTime())
13115
- : source && typeof source === 'object'
13116
- ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
13117
- Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop));
13118
- o[prop] = deepCopy(source[prop]);
13119
- return o;
13120
- }, Object.create(Object.getPrototypeOf(source)))
13121
- : source;
13122
- }
13123
-
13124
- function matchMlinesInAnswer(parsedOffer, parsedAnswer, streamSignalerManager) {
13125
- parsedAnswer.session.groups = parsedOffer.session.groups;
13126
- parsedAnswer.media = parsedOffer.media.map((offerMline) => {
13127
- if (!offerMline.mid) {
13128
- throw new Error(`Offer mline is missing MID`);
13129
- }
13130
- const answerMline = parsedAnswer.media.find((m) => m.mid === offerMline.mid);
13131
- if (answerMline) {
13132
- if (answerMline instanceof AvMediaDescription) {
13133
- [...answerMline.codecs.values()].forEach((ci) => {
13134
- ci.fmtParams.set('x-google-start-bitrate', '60000');
13135
- });
13136
- }
13137
- return answerMline;
13138
- }
13139
- if (!(offerMline instanceof AvMediaDescription)) {
13140
- throw new Error(`Answer is missing a non-media mline: ${offerMline.mid}`);
13141
- }
13142
- const startingMline = parsedAnswer.avMedia.find((m) => m.type === offerMline.type);
13143
- if (!startingMline) {
13144
- throw new Error(`Answer has no mline of type ${offerMline.type}, can't generate synthetic answer mline for mid ${offerMline.mid}`);
13145
- }
13146
- const fakeCorrespondingMline = deepCopy(startingMline);
13147
- fakeCorrespondingMline.mid = offerMline.mid;
13148
- fakeCorrespondingMline.simulcast = undefined;
13149
- if (offerMline.direction === 'sendrecv' || offerMline.direction === 'sendonly') {
13150
- fakeCorrespondingMline.direction = 'recvonly';
13151
- }
13152
- if (offerMline.direction === 'recvonly') {
13153
- fakeCorrespondingMline.direction = 'sendonly';
13154
- const ingressSignaler = streamSignalerManager.getIngressStreamSignalerOrThrow(offerMline.mid);
13155
- ingressSignaler.signalRemoteStreams(fakeCorrespondingMline);
13156
- }
13157
- return fakeCorrespondingMline;
13158
- });
13159
- }
13160
-
13161
13135
  function toMediaStreamTrackKind(mediaType) {
13162
13136
  return [MediaType.VideoMain, MediaType.VideoSlides].includes(mediaType)
13163
13137
  ? exports.MediaStreamTrackKind.Video
@@ -13244,7 +13218,7 @@ class MultistreamConnection extends EventEmitter {
13244
13218
  (_a = this.pc) === null || _a === void 0 ? void 0 : _a.close();
13245
13219
  this.pc = new PeerConnection({
13246
13220
  iceServers: this.options.iceServers,
13247
- bundlePolicy: getBrowserDetails().name === 'Firefox' ? 'max-compat' : this.options.bundlePolicy,
13221
+ bundlePolicy: this.options.bundlePolicy,
13248
13222
  });
13249
13223
  this.pc.on(PeerConnection.Events.ConnectionStateChange, (state) => this.emit(exports.MultistreamConnectionEventNames.ConnectionStateUpdate, state));
13250
13224
  this.attachMetricsObserver();
@@ -13628,6 +13602,7 @@ class MultistreamConnection extends EventEmitter {
13628
13602
  }
13629
13603
  return new Promise((createOfferResolve) => {
13630
13604
  this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
13605
+ var _a;
13631
13606
  if (this.setAnswerResolve !== undefined) {
13632
13607
  throw new Error(`Tried to start a new createOffer flow before the old one had finished`);
13633
13608
  }
@@ -13640,12 +13615,8 @@ class MultistreamConnection extends EventEmitter {
13640
13615
  }
13641
13616
  offer.sdp = this.preProcessLocalOffer(offer.sdp);
13642
13617
  yield this.pc.setLocalDescription(offer);
13643
- const offerWithCandidates = yield getLocalDescriptionWithIceCandidates(this.pc);
13644
- const sdpToSend = this.prepareLocalOfferForRemoteServer(offerWithCandidates.sdp);
13645
- createOfferResolve({
13646
- sdp: sdpToSend,
13647
- type: offerWithCandidates.type,
13648
- });
13618
+ const sdpToSend = this.prepareLocalOfferForRemoteServer((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
13619
+ createOfferResolve({ type: 'offer', sdp: sdpToSend });
13649
13620
  yield setAnswerPromise;
13650
13621
  }));
13651
13622
  });
@@ -13754,6 +13725,7 @@ class MultistreamConnection extends EventEmitter {
13754
13725
  });
13755
13726
  injectJmpAttributes(parsed, csiMap, this.options.streamSignalingMode);
13756
13727
  filterRecvOnlyMlines(parsed);
13728
+ injectDummyCandidates(parsed);
13757
13729
  parsed.avMedia
13758
13730
  .filter((av) => av.direction === 'sendrecv' && av.type === 'video')
13759
13731
  .forEach((av) => {
@@ -13766,6 +13738,13 @@ class MultistreamConnection extends EventEmitter {
13766
13738
  });
13767
13739
  if (getBrowserDetails().name === 'Firefox') {
13768
13740
  setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13741
+ if (this.options.bundlePolicy === 'max-bundle') {
13742
+ parsed.media.forEach((mline, index) => {
13743
+ if (index > 0) {
13744
+ mline.port = parsed.media[0].port;
13745
+ }
13746
+ });
13747
+ }
13769
13748
  }
13770
13749
  return parsed.toString();
13771
13750
  }
@@ -13776,6 +13755,15 @@ class MultistreamConnection extends EventEmitter {
13776
13755
  matchMlinesInAnswer(parsedOffer, parsedAnswer, this.streamSignalerManager);
13777
13756
  if (getBrowserDetails().name === 'Firefox') {
13778
13757
  setupBundle(parsedAnswer, this.options.bundlePolicy, this.midMap);
13758
+ if (this.options.bundlePolicy === 'max-bundle') {
13759
+ const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
13760
+ parsedAnswer.media.forEach((mline, index) => {
13761
+ if (index > 0) {
13762
+ mline.iceInfo.ufrag = ufrag;
13763
+ mline.iceInfo.pwd = pwd;
13764
+ }
13765
+ });
13766
+ }
13779
13767
  }
13780
13768
  return parsedAnswer.toString();
13781
13769
  }