@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/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,13 @@ 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('dummy', 1, 'udp', 1, '0.0.0.0', 1, 'host'));
9196
+ }
9197
+ });
9198
+ }
9174
9199
  function hasSimulcast(av) {
9175
9200
  return !!av.simulcast || av.ssrcGroups.map((sg) => sg.semantics).some((sem) => sem === 'SIM');
9176
9201
  }
@@ -13105,59 +13130,6 @@ function setLogHandler(logHandler) {
13105
13130
  Logger$2.setHandler(logHandler);
13106
13131
  }
13107
13132
 
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
13133
  function toMediaStreamTrackKind(mediaType) {
13162
13134
  return [MediaType.VideoMain, MediaType.VideoSlides].includes(mediaType)
13163
13135
  ? exports.MediaStreamTrackKind.Video
@@ -13244,7 +13216,7 @@ class MultistreamConnection extends EventEmitter {
13244
13216
  (_a = this.pc) === null || _a === void 0 ? void 0 : _a.close();
13245
13217
  this.pc = new PeerConnection({
13246
13218
  iceServers: this.options.iceServers,
13247
- bundlePolicy: getBrowserDetails().name === 'Firefox' ? 'max-compat' : this.options.bundlePolicy,
13219
+ bundlePolicy: this.options.bundlePolicy,
13248
13220
  });
13249
13221
  this.pc.on(PeerConnection.Events.ConnectionStateChange, (state) => this.emit(exports.MultistreamConnectionEventNames.ConnectionStateUpdate, state));
13250
13222
  this.attachMetricsObserver();
@@ -13628,6 +13600,7 @@ class MultistreamConnection extends EventEmitter {
13628
13600
  }
13629
13601
  return new Promise((createOfferResolve) => {
13630
13602
  this.offerAnswerQueue.push(() => __awaiter(this, void 0, void 0, function* () {
13603
+ var _a;
13631
13604
  if (this.setAnswerResolve !== undefined) {
13632
13605
  throw new Error(`Tried to start a new createOffer flow before the old one had finished`);
13633
13606
  }
@@ -13640,12 +13613,8 @@ class MultistreamConnection extends EventEmitter {
13640
13613
  }
13641
13614
  offer.sdp = this.preProcessLocalOffer(offer.sdp);
13642
13615
  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
- });
13616
+ const sdpToSend = this.prepareLocalOfferForRemoteServer((_a = this.pc.getLocalDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
13617
+ createOfferResolve({ type: 'offer', sdp: sdpToSend });
13649
13618
  yield setAnswerPromise;
13650
13619
  }));
13651
13620
  });
@@ -13754,6 +13723,7 @@ class MultistreamConnection extends EventEmitter {
13754
13723
  });
13755
13724
  injectJmpAttributes(parsed, csiMap, this.options.streamSignalingMode);
13756
13725
  filterRecvOnlyMlines(parsed);
13726
+ injectDummyCandidates(parsed);
13757
13727
  parsed.avMedia
13758
13728
  .filter((av) => av.direction === 'sendrecv' && av.type === 'video')
13759
13729
  .forEach((av) => {
@@ -13766,6 +13736,13 @@ class MultistreamConnection extends EventEmitter {
13766
13736
  });
13767
13737
  if (getBrowserDetails().name === 'Firefox') {
13768
13738
  setupBundle(parsed, this.options.bundlePolicy, this.midMap);
13739
+ if (this.options.bundlePolicy === 'max-bundle') {
13740
+ parsed.media.forEach((mline, index) => {
13741
+ if (index > 0) {
13742
+ mline.port = parsed.media[0].port;
13743
+ }
13744
+ });
13745
+ }
13769
13746
  }
13770
13747
  return parsed.toString();
13771
13748
  }
@@ -13776,6 +13753,15 @@ class MultistreamConnection extends EventEmitter {
13776
13753
  matchMlinesInAnswer(parsedOffer, parsedAnswer, this.streamSignalerManager);
13777
13754
  if (getBrowserDetails().name === 'Firefox') {
13778
13755
  setupBundle(parsedAnswer, this.options.bundlePolicy, this.midMap);
13756
+ if (this.options.bundlePolicy === 'max-bundle') {
13757
+ const { ufrag, pwd } = parsedAnswer.media[0].iceInfo;
13758
+ parsedAnswer.media.forEach((mline, index) => {
13759
+ if (index > 0) {
13760
+ mline.iceInfo.ufrag = ufrag;
13761
+ mline.iceInfo.pwd = pwd;
13762
+ }
13763
+ });
13764
+ }
13779
13765
  }
13780
13766
  return parsedAnswer.toString();
13781
13767
  }