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

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/esm/index.js CHANGED
@@ -5130,41 +5130,6 @@ class PeerConnection extends EventEmitter$2 {
5130
5130
  }
5131
5131
  PeerConnection.Events = PeerConnectionEvents;
5132
5132
 
5133
- /**
5134
- * Wait until the given peer connection has finished gathering ICE candidates and, when it has,
5135
- * return the local description with the candidates.
5136
- *
5137
- * @param peerConnection - The PeerConnection to use.
5138
- * @returns A Promise that resolves with the local description with the ICE candidates in it.
5139
- */
5140
- function getLocalDescriptionWithIceCandidates(peerConnection) {
5141
- return new Promise((resolve, reject) => {
5142
- /**
5143
- * A helper method to retrieve the local description and resolve, if one is found, or reject
5144
- * with an error if it's not.
5145
- */
5146
- const getLocalDescAndResolve = () => {
5147
- const localDesc = peerConnection.getLocalDescription();
5148
- if (localDesc) {
5149
- resolve(localDesc);
5150
- }
5151
- else {
5152
- reject(new Error('Local description was null'));
5153
- }
5154
- };
5155
- peerConnection.on(PeerConnection.Events.IceGatheringStateChange, (e) => {
5156
- if (e.target.iceGatheringState === 'complete') {
5157
- getLocalDescAndResolve();
5158
- }
5159
- // TODO(brian): throw an error if we see an error iceGatheringState
5160
- });
5161
- // It's possible ICE gathering is already done
5162
- if (peerConnection.iceGatheringState === 'complete') {
5163
- getLocalDescAndResolve();
5164
- }
5165
- });
5166
- }
5167
-
5168
5133
  var MediaCodecMimeType;
5169
5134
  (function (MediaCodecMimeType) {
5170
5135
  MediaCodecMimeType["H264"] = "video/H264";
@@ -9003,6 +8968,59 @@ class ReceiveOnlyTransceiver extends Transceiver {
9003
8968
  }
9004
8969
  ReceiveOnlyTransceiver.rid = '1';
9005
8970
 
8971
+ function deepCopy(source) {
8972
+ return Array.isArray(source)
8973
+ ? source.map((item) => deepCopy(item))
8974
+ : source instanceof Map
8975
+ ? new Map(source)
8976
+ : source instanceof Date
8977
+ ? new Date(source.getTime())
8978
+ : source && typeof source === 'object'
8979
+ ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
8980
+ Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop));
8981
+ o[prop] = deepCopy(source[prop]);
8982
+ return o;
8983
+ }, Object.create(Object.getPrototypeOf(source)))
8984
+ : source;
8985
+ }
8986
+
8987
+ function matchMlinesInAnswer(parsedOffer, parsedAnswer, streamSignalerManager) {
8988
+ parsedAnswer.session.groups = parsedOffer.session.groups;
8989
+ parsedAnswer.media = parsedOffer.media.map((offerMline) => {
8990
+ if (!offerMline.mid) {
8991
+ throw new Error(`Offer mline is missing MID`);
8992
+ }
8993
+ const answerMline = parsedAnswer.media.find((m) => m.mid === offerMline.mid);
8994
+ if (answerMline) {
8995
+ if (answerMline instanceof AvMediaDescription) {
8996
+ [...answerMline.codecs.values()].forEach((ci) => {
8997
+ ci.fmtParams.set('x-google-start-bitrate', '60000');
8998
+ });
8999
+ }
9000
+ return answerMline;
9001
+ }
9002
+ if (!(offerMline instanceof AvMediaDescription)) {
9003
+ throw new Error(`Answer is missing a non-media mline: ${offerMline.mid}`);
9004
+ }
9005
+ const startingMline = parsedAnswer.avMedia.find((m) => m.type === offerMline.type);
9006
+ if (!startingMline) {
9007
+ throw new Error(`Answer has no mline of type ${offerMline.type}, can't generate synthetic answer mline for mid ${offerMline.mid}`);
9008
+ }
9009
+ const fakeCorrespondingMline = deepCopy(startingMline);
9010
+ fakeCorrespondingMline.mid = offerMline.mid;
9011
+ fakeCorrespondingMline.simulcast = undefined;
9012
+ if (offerMline.direction === 'sendrecv' || offerMline.direction === 'sendonly') {
9013
+ fakeCorrespondingMline.direction = 'recvonly';
9014
+ }
9015
+ if (offerMline.direction === 'recvonly') {
9016
+ fakeCorrespondingMline.direction = 'sendonly';
9017
+ const ingressSignaler = streamSignalerManager.getIngressStreamSignalerOrThrow(offerMline.mid);
9018
+ ingressSignaler.signalRemoteStreams(fakeCorrespondingMline);
9019
+ }
9020
+ return fakeCorrespondingMline;
9021
+ });
9022
+ }
9023
+
9006
9024
  class JmpLine extends Line {
9007
9025
  constructor(versions) {
9008
9026
  super();
@@ -9167,6 +9185,13 @@ function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
9167
9185
  }
9168
9186
  });
9169
9187
  }
9188
+ function injectDummyCandidates(parsedSdp) {
9189
+ parsedSdp.media.forEach((mLine) => {
9190
+ if (mLine.iceInfo.candidates.length === 0) {
9191
+ mLine.addLine(new CandidateLine('dummy', 1, 'udp', 1, '0.0.0.0', 1, 'host'));
9192
+ }
9193
+ });
9194
+ }
9170
9195
  function hasSimulcast(av) {
9171
9196
  return !!av.simulcast || av.ssrcGroups.map((sg) => sg.semantics).some((sem) => sem === 'SIM');
9172
9197
  }
@@ -13101,59 +13126,6 @@ function setLogHandler(logHandler) {
13101
13126
  Logger$2.setHandler(logHandler);
13102
13127
  }
13103
13128
 
13104
- function deepCopy(source) {
13105
- return Array.isArray(source)
13106
- ? source.map((item) => deepCopy(item))
13107
- : source instanceof Map
13108
- ? new Map(source)
13109
- : source instanceof Date
13110
- ? new Date(source.getTime())
13111
- : source && typeof source === 'object'
13112
- ? Object.getOwnPropertyNames(source).reduce((o, prop) => {
13113
- Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop));
13114
- o[prop] = deepCopy(source[prop]);
13115
- return o;
13116
- }, Object.create(Object.getPrototypeOf(source)))
13117
- : source;
13118
- }
13119
-
13120
- function matchMlinesInAnswer(parsedOffer, parsedAnswer, streamSignalerManager) {
13121
- parsedAnswer.session.groups = parsedOffer.session.groups;
13122
- parsedAnswer.media = parsedOffer.media.map((offerMline) => {
13123
- if (!offerMline.mid) {
13124
- throw new Error(`Offer mline is missing MID`);
13125
- }
13126
- const answerMline = parsedAnswer.media.find((m) => m.mid === offerMline.mid);
13127
- if (answerMline) {
13128
- if (answerMline instanceof AvMediaDescription) {
13129
- [...answerMline.codecs.values()].forEach((ci) => {
13130
- ci.fmtParams.set('x-google-start-bitrate', '60000');
13131
- });
13132
- }
13133
- return answerMline;
13134
- }
13135
- if (!(offerMline instanceof AvMediaDescription)) {
13136
- throw new Error(`Answer is missing a non-media mline: ${offerMline.mid}`);
13137
- }
13138
- const startingMline = parsedAnswer.avMedia.find((m) => m.type === offerMline.type);
13139
- if (!startingMline) {
13140
- throw new Error(`Answer has no mline of type ${offerMline.type}, can't generate synthetic answer mline for mid ${offerMline.mid}`);
13141
- }
13142
- const fakeCorrespondingMline = deepCopy(startingMline);
13143
- fakeCorrespondingMline.mid = offerMline.mid;
13144
- fakeCorrespondingMline.simulcast = undefined;
13145
- if (offerMline.direction === 'sendrecv' || offerMline.direction === 'sendonly') {
13146
- fakeCorrespondingMline.direction = 'recvonly';
13147
- }
13148
- if (offerMline.direction === 'recvonly') {
13149
- fakeCorrespondingMline.direction = 'sendonly';
13150
- const ingressSignaler = streamSignalerManager.getIngressStreamSignalerOrThrow(offerMline.mid);
13151
- ingressSignaler.signalRemoteStreams(fakeCorrespondingMline);
13152
- }
13153
- return fakeCorrespondingMline;
13154
- });
13155
- }
13156
-
13157
13129
  function toMediaStreamTrackKind(mediaType) {
13158
13130
  return [MediaType.VideoMain, MediaType.VideoSlides].includes(mediaType)
13159
13131
  ? MediaStreamTrackKind.Video
@@ -13240,7 +13212,7 @@ class MultistreamConnection extends EventEmitter {
13240
13212
  (_a = this.pc) === null || _a === void 0 ? void 0 : _a.close();
13241
13213
  this.pc = new PeerConnection({
13242
13214
  iceServers: this.options.iceServers,
13243
- bundlePolicy: getBrowserDetails().name === 'Firefox' ? 'max-compat' : this.options.bundlePolicy,
13215
+ bundlePolicy: this.options.bundlePolicy,
13244
13216
  });
13245
13217
  this.pc.on(PeerConnection.Events.ConnectionStateChange, (state) => this.emit(MultistreamConnectionEventNames.ConnectionStateUpdate, state));
13246
13218
  this.attachMetricsObserver();
@@ -13624,6 +13596,7 @@ class MultistreamConnection extends EventEmitter {
13624
13596
  }
13625
13597
  return new Promise((createOfferResolve) => {
13626
13598
  this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
13599
+ var _a;
13627
13600
  if (this.setAnswerResolve !== undefined) {
13628
13601
  throw new Error(`Tried to start a new createOffer flow before the old one had finished`);
13629
13602
  }
@@ -13636,12 +13609,8 @@ class MultistreamConnection extends EventEmitter {
13636
13609
  }
13637
13610
  offer.sdp = this.preProcessLocalOffer(offer.sdp);
13638
13611
  yield this.pc.setLocalDescription(offer);
13639
- const offerWithCandidates = yield getLocalDescriptionWithIceCandidates(this.pc);
13640
- const sdpToSend = this.prepareLocalOfferForRemoteServer(offerWithCandidates.sdp);
13641
- createOfferResolve({
13642
- sdp: sdpToSend,
13643
- type: offerWithCandidates.type,
13644
- });
13612
+ const sdpToSend = this.prepareLocalOfferForRemoteServer((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
13613
+ createOfferResolve({ type: 'offer', sdp: sdpToSend });
13645
13614
  yield setAnswerPromise;
13646
13615
  }));
13647
13616
  });
@@ -13750,6 +13719,7 @@ class MultistreamConnection extends EventEmitter {
13750
13719
  });
13751
13720
  injectJmpAttributes(parsed, csiMap, this.options.streamSignalingMode);
13752
13721
  filterRecvOnlyMlines(parsed);
13722
+ injectDummyCandidates(parsed);
13753
13723
  parsed.avMedia
13754
13724
  .filter((av) => av.direction === 'sendrecv' && av.type === 'video')
13755
13725
  .forEach((av) => {
@@ -13762,6 +13732,13 @@ class MultistreamConnection extends EventEmitter {
13762
13732
  });
13763
13733
  if (getBrowserDetails().name === 'Firefox') {
13764
13734
  setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13735
+ if (this.options.bundlePolicy === 'max-bundle') {
13736
+ parsed.media.forEach((mline, index) => {
13737
+ if (index > 0) {
13738
+ mline.port = parsed.media[0].port;
13739
+ }
13740
+ });
13741
+ }
13765
13742
  }
13766
13743
  return parsed.toString();
13767
13744
  }
@@ -13772,6 +13749,15 @@ class MultistreamConnection extends EventEmitter {
13772
13749
  matchMlinesInAnswer(parsedOffer, parsedAnswer, this.streamSignalerManager);
13773
13750
  if (getBrowserDetails().name === 'Firefox') {
13774
13751
  setupBundle(parsedAnswer, this.options.bundlePolicy, this.midMap);
13752
+ if (this.options.bundlePolicy === 'max-bundle') {
13753
+ const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
13754
+ parsedAnswer.media.forEach((mline, index) => {
13755
+ if (index > 0) {
13756
+ mline.iceInfo.ufrag = ufrag;
13757
+ mline.iceInfo.pwd = pwd;
13758
+ }
13759
+ });
13760
+ }
13775
13761
  }
13776
13762
  return parsedAnswer.toString();
13777
13763
  }