@webex/plugin-meetings 3.0.0-beta.140 → 3.0.0-beta.142

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.
@@ -206,13 +206,15 @@ var MediaRequestManager = /*#__PURE__*/function () {
206
206
  // eslint-disable-next-line no-plusplus
207
207
  var newId = "".concat(this.counter++);
208
208
  this.clientRequests[newId] = mediaRequest;
209
+ var eventHandler = function eventHandler(_ref3) {
210
+ var maxFs = _ref3.maxFs;
211
+ mediaRequest.preferredMaxFs = maxFs;
212
+ _this4.debouncedSourceUpdateListener();
213
+ };
214
+ mediaRequest.handleMaxFs = eventHandler;
209
215
  mediaRequest.receiveSlots.forEach(function (rs) {
210
216
  rs.on(_receiveSlot.ReceiveSlotEvents.SourceUpdate, _this4.sourceUpdateListener);
211
- rs.on(_receiveSlot.ReceiveSlotEvents.MaxFsUpdate, function (_ref3) {
212
- var maxFs = _ref3.maxFs;
213
- mediaRequest.preferredMaxFs = maxFs;
214
- _this4.debouncedSourceUpdateListener();
215
- });
217
+ rs.on(_receiveSlot.ReceiveSlotEvents.MaxFsUpdate, mediaRequest.handleMaxFs);
216
218
  });
217
219
  if (commit) {
218
220
  this.commit();
@@ -222,11 +224,12 @@ var MediaRequestManager = /*#__PURE__*/function () {
222
224
  }, {
223
225
  key: "cancelRequest",
224
226
  value: function cancelRequest(requestId) {
225
- var _this$clientRequests$,
226
- _this5 = this;
227
+ var _this5 = this;
227
228
  var commit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
228
- (_this$clientRequests$ = this.clientRequests[requestId]) === null || _this$clientRequests$ === void 0 ? void 0 : _this$clientRequests$.receiveSlots.forEach(function (rs) {
229
+ var mediaRequest = this.clientRequests[requestId];
230
+ mediaRequest === null || mediaRequest === void 0 ? void 0 : mediaRequest.receiveSlots.forEach(function (rs) {
229
231
  rs.off(_receiveSlot.ReceiveSlotEvents.SourceUpdate, _this5.sourceUpdateListener);
232
+ rs.off(_receiveSlot.ReceiveSlotEvents.MaxFsUpdate, mediaRequest.handleMaxFs);
230
233
  });
231
234
  delete this.clientRequests[requestId];
232
235
  if (commit) {
@@ -1 +1 @@
1
- {"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","DEBOUNCED_SOURCE_UPDATE_TIME","MediaRequestManager","sendMediaRequestsCallback","options","counter","clientRequests","degradationPreferences","kind","sourceUpdateListener","commit","bind","debouncedSourceUpdateListener","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","id","mr","codecInfo","Math","min","preferredMaxFs","i","slotsWithLiveSource","receiveSlots","filter","rs","sourceState","length","maxMacroblocksLimit","LoggerProxy","logger","warn","streamRequestA","streamRequestB","_toJmpStreamRequest","newRequests","previousStreamRequests","every","req","idx","isEqual","mediaRequest","RecommendedOpusBitrates","FB_MONO_MUSIC","getRecommendedMaxBitrateForFrameSize","streamRequests","getDegradedClientRequests","push","StreamRequest","policyInfo","policy","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","priority","crossPriorityDuplication","crossPolicyDuplication","preferLiveVideo","ReceiverSelectedInfo","csi","map","receiveSlot","wcmeReceiveSlot","getMaxPayloadBitsPerSecond","WcmeCodecInfo","H264Codec","getH264MaxMbps","maxWidth","maxHeight","checkIsNewRequestsEqualToPrev","info","newId","on","ReceiveSlotEvents","SourceUpdate","MaxFsUpdate","requestId","off"],"sources":["mediaRequestManager.ts"],"sourcesContent":["/* eslint-disable require-jsdoc */\nimport {\n StreamRequest,\n Policy,\n ActiveSpeakerInfo,\n ReceiverSelectedInfo,\n CodecInfo as WcmeCodecInfo,\n H264Codec,\n getRecommendedMaxBitrateForFrameSize,\n RecommendedOpusBitrates,\n} from '@webex/internal-media-core';\nimport {cloneDeep, debounce, isEmpty} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';\nimport {getMaxFs} from './remoteMedia';\n\nexport interface ActiveSpeakerPolicyInfo {\n policy: 'active-speaker';\n priority: number;\n crossPriorityDuplication: boolean;\n crossPolicyDuplication: boolean;\n preferLiveVideo: boolean;\n}\n\nexport interface ReceiverSelectedPolicyInfo {\n policy: 'receiver-selected';\n csi: number;\n}\n\nexport type PolicyInfo = ActiveSpeakerPolicyInfo | ReceiverSelectedPolicyInfo;\n\nexport interface H264CodecInfo {\n codec: 'h264';\n maxFs?: number;\n maxFps?: number;\n maxMbps?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\nexport type CodecInfo = H264CodecInfo; // we'll add AV1 here in the future when it's available\n\nexport interface MediaRequest {\n policyInfo: PolicyInfo;\n receiveSlots: Array<ReceiveSlot>;\n codecInfo?: CodecInfo;\n preferredMaxFs?: number;\n}\n\nexport type MediaRequestId = string;\n\nconst CODEC_DEFAULTS = {\n h264: {\n maxFs: 8192,\n maxFps: 3000,\n maxMbps: 245760,\n },\n};\n\nconst DEBOUNCED_SOURCE_UPDATE_TIME = 1000;\n\ntype DegradationPreferences = {\n maxMacroblocksLimit: number;\n};\n\ntype SendMediaRequestsCallback = (streamRequests: StreamRequest[]) => void;\ntype Kind = 'audio' | 'video';\n\ntype Options = {\n degradationPreferences: DegradationPreferences;\n kind: Kind;\n};\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private kind: Kind;\n\n private counter: number;\n\n private clientRequests: {[key: MediaRequestId]: MediaRequest};\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n private debouncedSourceUpdateListener: () => void;\n\n private previousStreamRequests: Array<StreamRequest> = [];\n\n constructor(sendMediaRequestsCallback: SendMediaRequestsCallback, options: Options) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.clientRequests = {};\n this.degradationPreferences = options.degradationPreferences;\n this.kind = options.kind;\n this.sourceUpdateListener = this.commit.bind(this);\n this.debouncedSourceUpdateListener = debounce(\n this.sourceUpdateListener,\n DEBOUNCED_SOURCE_UPDATE_TIME\n );\n }\n\n public setDegradationPreferences(degradationPreferences: DegradationPreferences) {\n this.degradationPreferences = degradationPreferences;\n this.sendRequests(); // re-send requests after preferences are set\n }\n\n private getDegradedClientRequests() {\n const clientRequests = cloneDeep(this.clientRequests);\n const maxFsLimits = [\n getMaxFs('best'),\n getMaxFs('large'),\n getMaxFs('medium'),\n getMaxFs('small'),\n getMaxFs('very small'),\n getMaxFs('thumbnail'),\n ];\n\n // reduce max-fs until total macroblocks is below limit\n for (let i = 0; i < maxFsLimits.length; i += 1) {\n let totalMacroblocksRequested = 0;\n Object.entries(clientRequests).forEach(([id, mr]) => {\n if (mr.codecInfo) {\n mr.codecInfo.maxFs = Math.min(\n mr.preferredMaxFs || CODEC_DEFAULTS.h264.maxFs,\n mr.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs,\n maxFsLimits[i]\n );\n // we only consider sources with \"live\" state\n const slotsWithLiveSource = this.clientRequests[id].receiveSlots.filter(\n (rs) => rs.sourceState === 'live'\n );\n totalMacroblocksRequested += mr.codecInfo.maxFs * slotsWithLiveSource.length;\n }\n });\n if (totalMacroblocksRequested <= this.degradationPreferences.maxMacroblocksLimit) {\n if (i !== 0) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> too many streams with high max-fs, frame size will be limited to ${maxFsLimits[i]}`\n );\n }\n break;\n } else if (i === maxFsLimits.length - 1) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> even with frame size limited to ${maxFsLimits[i]} you are still requesting too many streams, consider reducing the number of requests`\n );\n }\n }\n\n return clientRequests;\n }\n\n /**\n * Returns true if two stream requests are the same, false otherwise.\n *\n * @param {StreamRequest} streamRequestA - Stream request A for comparison.\n * @param {StreamRequest} streamRequestB - Stream request B for comparison.\n * @returns {boolean} - Whether they are equal.\n */\n // eslint-disable-next-line class-methods-use-this\n public isEqual(streamRequestA: StreamRequest, streamRequestB: StreamRequest) {\n return (\n JSON.stringify(streamRequestA._toJmpStreamRequest()) ===\n JSON.stringify(streamRequestB._toJmpStreamRequest())\n );\n }\n\n /**\n * Compares new stream requests to previous ones and determines\n * if they are the same.\n *\n * @param {StreamRequest[]} newRequests - Array with new requests.\n * @returns {boolean} - True if they are equal, false otherwise.\n */\n private checkIsNewRequestsEqualToPrev(newRequests: StreamRequest[]) {\n return (\n !isEmpty(this.previousStreamRequests) &&\n this.previousStreamRequests.length === newRequests.length &&\n this.previousStreamRequests.every((req, idx) => this.isEqual(req, newRequests[idx]))\n );\n }\n\n /**\n * Returns the maxPayloadBitsPerSecond per Stream\n *\n * If MediaRequestManager kind is \"audio\", a constant bitrate will be returned.\n * If MediaRequestManager kind is \"video\", the bitrate will be calculated based\n * on maxFs (default h264 maxFs as fallback if maxFs is not defined)\n *\n * @param {MediaRequest} mediaRequest - mediaRequest to take data from\n * @returns {number} maxPayloadBitsPerSecond\n */\n private getMaxPayloadBitsPerSecond(mediaRequest: MediaRequest): number {\n if (this.kind === 'audio') {\n // return mono_music bitrate default if the kind of mediarequest manager is audio:\n return RecommendedOpusBitrates.FB_MONO_MUSIC;\n }\n\n return getRecommendedMaxBitrateForFrameSize(\n mediaRequest.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs\n );\n }\n\n /**\n * Returns the max Macro Blocks per second (maxMbps) per H264 Stream\n *\n * The maxMbps will be calculated based on maxFs and maxFps\n * (default h264 maxFps as fallback if maxFps is not defined)\n *\n * @param {MediaRequest} mediaRequest - mediaRequest to take data from\n * @returns {number} maxMbps\n */\n // eslint-disable-next-line class-methods-use-this\n private getH264MaxMbps(mediaRequest: MediaRequest): number {\n // fallback for maxFps (not needed for maxFs, since there is a fallback already in getDegradedClientRequests)\n const maxFps = mediaRequest.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps;\n\n // divided by 100 since maxFps is 3000 (for 30 frames per seconds)\n return (mediaRequest.codecInfo.maxFs * maxFps) / 100;\n }\n\n /**\n * Clears the previous stream requests.\n *\n * @returns {void}\n */\n public clearPreviousRequests(): void {\n this.previousStreamRequests = [];\n }\n\n private sendRequests() {\n const streamRequests: StreamRequest[] = [];\n\n const clientRequests = this.getDegradedClientRequests();\n\n // map all the client media requests to wcme stream requests\n Object.values(clientRequests).forEach((mr) => {\n streamRequests.push(\n new StreamRequest(\n mr.policyInfo.policy === 'active-speaker'\n ? Policy.ActiveSpeaker\n : Policy.ReceiverSelected,\n mr.policyInfo.policy === 'active-speaker'\n ? new ActiveSpeakerInfo(\n mr.policyInfo.priority,\n mr.policyInfo.crossPriorityDuplication,\n mr.policyInfo.crossPolicyDuplication,\n mr.policyInfo.preferLiveVideo\n )\n : new ReceiverSelectedInfo(mr.policyInfo.csi),\n mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),\n this.getMaxPayloadBitsPerSecond(mr),\n mr.codecInfo && [\n new WcmeCodecInfo(\n 0x80,\n new H264Codec(\n mr.codecInfo.maxFs,\n mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,\n this.getH264MaxMbps(mr),\n mr.codecInfo.maxWidth,\n mr.codecInfo.maxHeight\n )\n ),\n ]\n )\n );\n });\n\n //! IMPORTANT: this is only a temporary fix. This will soon be done in the jmp layer (@webex/json-multistream)\n // https://jira-eng-gpk2.cisco.com/jira/browse/WEBEX-326713\n if (!this.checkIsNewRequestsEqualToPrev(streamRequests)) {\n this.sendMediaRequestsCallback(streamRequests);\n this.previousStreamRequests = streamRequests;\n LoggerProxy.logger.info(`multistream:sendRequests --> media requests sent. `);\n } else {\n LoggerProxy.logger.info(\n `multistream:sendRequests --> detected duplicate WCME requests, skipping them... `\n );\n }\n }\n\n public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {\n // eslint-disable-next-line no-plusplus\n const newId = `${this.counter++}`;\n\n this.clientRequests[newId] = mediaRequest;\n\n mediaRequest.receiveSlots.forEach((rs) => {\n rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n rs.on(ReceiveSlotEvents.MaxFsUpdate, ({maxFs}) => {\n mediaRequest.preferredMaxFs = maxFs;\n this.debouncedSourceUpdateListener();\n });\n });\n\n if (commit) {\n this.commit();\n }\n\n return newId;\n }\n\n public cancelRequest(requestId: MediaRequestId, commit = true) {\n this.clientRequests[requestId]?.receiveSlots.forEach((rs) => {\n rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n delete this.clientRequests[requestId];\n\n if (commit) {\n this.commit();\n }\n }\n\n public commit() {\n return this.sendRequests();\n }\n\n public reset() {\n this.clientRequests = {};\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","DEBOUNCED_SOURCE_UPDATE_TIME","MediaRequestManager","sendMediaRequestsCallback","options","counter","clientRequests","degradationPreferences","kind","sourceUpdateListener","commit","bind","debouncedSourceUpdateListener","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","id","mr","codecInfo","Math","min","preferredMaxFs","i","slotsWithLiveSource","receiveSlots","filter","rs","sourceState","length","maxMacroblocksLimit","LoggerProxy","logger","warn","streamRequestA","streamRequestB","_toJmpStreamRequest","newRequests","previousStreamRequests","every","req","idx","isEqual","mediaRequest","RecommendedOpusBitrates","FB_MONO_MUSIC","getRecommendedMaxBitrateForFrameSize","streamRequests","getDegradedClientRequests","push","StreamRequest","policyInfo","policy","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","priority","crossPriorityDuplication","crossPolicyDuplication","preferLiveVideo","ReceiverSelectedInfo","csi","map","receiveSlot","wcmeReceiveSlot","getMaxPayloadBitsPerSecond","WcmeCodecInfo","H264Codec","getH264MaxMbps","maxWidth","maxHeight","checkIsNewRequestsEqualToPrev","info","newId","eventHandler","handleMaxFs","on","ReceiveSlotEvents","SourceUpdate","MaxFsUpdate","requestId","off"],"sources":["mediaRequestManager.ts"],"sourcesContent":["/* eslint-disable require-jsdoc */\nimport {\n StreamRequest,\n Policy,\n ActiveSpeakerInfo,\n ReceiverSelectedInfo,\n CodecInfo as WcmeCodecInfo,\n H264Codec,\n getRecommendedMaxBitrateForFrameSize,\n RecommendedOpusBitrates,\n} from '@webex/internal-media-core';\nimport {cloneDeep, debounce, isEmpty} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';\nimport {getMaxFs} from './remoteMedia';\n\nexport interface ActiveSpeakerPolicyInfo {\n policy: 'active-speaker';\n priority: number;\n crossPriorityDuplication: boolean;\n crossPolicyDuplication: boolean;\n preferLiveVideo: boolean;\n}\n\nexport interface ReceiverSelectedPolicyInfo {\n policy: 'receiver-selected';\n csi: number;\n}\n\nexport type PolicyInfo = ActiveSpeakerPolicyInfo | ReceiverSelectedPolicyInfo;\n\nexport interface H264CodecInfo {\n codec: 'h264';\n maxFs?: number;\n maxFps?: number;\n maxMbps?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\nexport type CodecInfo = H264CodecInfo; // we'll add AV1 here in the future when it's available\n\nexport interface MediaRequest {\n policyInfo: PolicyInfo;\n receiveSlots: Array<ReceiveSlot>;\n codecInfo?: CodecInfo;\n preferredMaxFs?: number;\n handleMaxFs?: ({maxFs}: {maxFs: number}) => void;\n}\n\nexport type MediaRequestId = string;\n\nconst CODEC_DEFAULTS = {\n h264: {\n maxFs: 8192,\n maxFps: 3000,\n maxMbps: 245760,\n },\n};\n\nconst DEBOUNCED_SOURCE_UPDATE_TIME = 1000;\n\ntype DegradationPreferences = {\n maxMacroblocksLimit: number;\n};\n\ntype SendMediaRequestsCallback = (streamRequests: StreamRequest[]) => void;\ntype Kind = 'audio' | 'video';\n\ntype Options = {\n degradationPreferences: DegradationPreferences;\n kind: Kind;\n};\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private kind: Kind;\n\n private counter: number;\n\n private clientRequests: {[key: MediaRequestId]: MediaRequest};\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n private debouncedSourceUpdateListener: () => void;\n\n private previousStreamRequests: Array<StreamRequest> = [];\n\n constructor(sendMediaRequestsCallback: SendMediaRequestsCallback, options: Options) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.clientRequests = {};\n this.degradationPreferences = options.degradationPreferences;\n this.kind = options.kind;\n this.sourceUpdateListener = this.commit.bind(this);\n this.debouncedSourceUpdateListener = debounce(\n this.sourceUpdateListener,\n DEBOUNCED_SOURCE_UPDATE_TIME\n );\n }\n\n public setDegradationPreferences(degradationPreferences: DegradationPreferences) {\n this.degradationPreferences = degradationPreferences;\n this.sendRequests(); // re-send requests after preferences are set\n }\n\n private getDegradedClientRequests() {\n const clientRequests = cloneDeep(this.clientRequests);\n const maxFsLimits = [\n getMaxFs('best'),\n getMaxFs('large'),\n getMaxFs('medium'),\n getMaxFs('small'),\n getMaxFs('very small'),\n getMaxFs('thumbnail'),\n ];\n\n // reduce max-fs until total macroblocks is below limit\n for (let i = 0; i < maxFsLimits.length; i += 1) {\n let totalMacroblocksRequested = 0;\n Object.entries(clientRequests).forEach(([id, mr]) => {\n if (mr.codecInfo) {\n mr.codecInfo.maxFs = Math.min(\n mr.preferredMaxFs || CODEC_DEFAULTS.h264.maxFs,\n mr.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs,\n maxFsLimits[i]\n );\n // we only consider sources with \"live\" state\n const slotsWithLiveSource = this.clientRequests[id].receiveSlots.filter(\n (rs) => rs.sourceState === 'live'\n );\n totalMacroblocksRequested += mr.codecInfo.maxFs * slotsWithLiveSource.length;\n }\n });\n if (totalMacroblocksRequested <= this.degradationPreferences.maxMacroblocksLimit) {\n if (i !== 0) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> too many streams with high max-fs, frame size will be limited to ${maxFsLimits[i]}`\n );\n }\n break;\n } else if (i === maxFsLimits.length - 1) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> even with frame size limited to ${maxFsLimits[i]} you are still requesting too many streams, consider reducing the number of requests`\n );\n }\n }\n\n return clientRequests;\n }\n\n /**\n * Returns true if two stream requests are the same, false otherwise.\n *\n * @param {StreamRequest} streamRequestA - Stream request A for comparison.\n * @param {StreamRequest} streamRequestB - Stream request B for comparison.\n * @returns {boolean} - Whether they are equal.\n */\n // eslint-disable-next-line class-methods-use-this\n public isEqual(streamRequestA: StreamRequest, streamRequestB: StreamRequest) {\n return (\n JSON.stringify(streamRequestA._toJmpStreamRequest()) ===\n JSON.stringify(streamRequestB._toJmpStreamRequest())\n );\n }\n\n /**\n * Compares new stream requests to previous ones and determines\n * if they are the same.\n *\n * @param {StreamRequest[]} newRequests - Array with new requests.\n * @returns {boolean} - True if they are equal, false otherwise.\n */\n private checkIsNewRequestsEqualToPrev(newRequests: StreamRequest[]) {\n return (\n !isEmpty(this.previousStreamRequests) &&\n this.previousStreamRequests.length === newRequests.length &&\n this.previousStreamRequests.every((req, idx) => this.isEqual(req, newRequests[idx]))\n );\n }\n\n /**\n * Returns the maxPayloadBitsPerSecond per Stream\n *\n * If MediaRequestManager kind is \"audio\", a constant bitrate will be returned.\n * If MediaRequestManager kind is \"video\", the bitrate will be calculated based\n * on maxFs (default h264 maxFs as fallback if maxFs is not defined)\n *\n * @param {MediaRequest} mediaRequest - mediaRequest to take data from\n * @returns {number} maxPayloadBitsPerSecond\n */\n private getMaxPayloadBitsPerSecond(mediaRequest: MediaRequest): number {\n if (this.kind === 'audio') {\n // return mono_music bitrate default if the kind of mediarequest manager is audio:\n return RecommendedOpusBitrates.FB_MONO_MUSIC;\n }\n\n return getRecommendedMaxBitrateForFrameSize(\n mediaRequest.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs\n );\n }\n\n /**\n * Returns the max Macro Blocks per second (maxMbps) per H264 Stream\n *\n * The maxMbps will be calculated based on maxFs and maxFps\n * (default h264 maxFps as fallback if maxFps is not defined)\n *\n * @param {MediaRequest} mediaRequest - mediaRequest to take data from\n * @returns {number} maxMbps\n */\n // eslint-disable-next-line class-methods-use-this\n private getH264MaxMbps(mediaRequest: MediaRequest): number {\n // fallback for maxFps (not needed for maxFs, since there is a fallback already in getDegradedClientRequests)\n const maxFps = mediaRequest.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps;\n\n // divided by 100 since maxFps is 3000 (for 30 frames per seconds)\n return (mediaRequest.codecInfo.maxFs * maxFps) / 100;\n }\n\n /**\n * Clears the previous stream requests.\n *\n * @returns {void}\n */\n public clearPreviousRequests(): void {\n this.previousStreamRequests = [];\n }\n\n private sendRequests() {\n const streamRequests: StreamRequest[] = [];\n\n const clientRequests = this.getDegradedClientRequests();\n\n // map all the client media requests to wcme stream requests\n Object.values(clientRequests).forEach((mr) => {\n streamRequests.push(\n new StreamRequest(\n mr.policyInfo.policy === 'active-speaker'\n ? Policy.ActiveSpeaker\n : Policy.ReceiverSelected,\n mr.policyInfo.policy === 'active-speaker'\n ? new ActiveSpeakerInfo(\n mr.policyInfo.priority,\n mr.policyInfo.crossPriorityDuplication,\n mr.policyInfo.crossPolicyDuplication,\n mr.policyInfo.preferLiveVideo\n )\n : new ReceiverSelectedInfo(mr.policyInfo.csi),\n mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),\n this.getMaxPayloadBitsPerSecond(mr),\n mr.codecInfo && [\n new WcmeCodecInfo(\n 0x80,\n new H264Codec(\n mr.codecInfo.maxFs,\n mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,\n this.getH264MaxMbps(mr),\n mr.codecInfo.maxWidth,\n mr.codecInfo.maxHeight\n )\n ),\n ]\n )\n );\n });\n\n //! IMPORTANT: this is only a temporary fix. This will soon be done in the jmp layer (@webex/json-multistream)\n // https://jira-eng-gpk2.cisco.com/jira/browse/WEBEX-326713\n if (!this.checkIsNewRequestsEqualToPrev(streamRequests)) {\n this.sendMediaRequestsCallback(streamRequests);\n this.previousStreamRequests = streamRequests;\n LoggerProxy.logger.info(`multistream:sendRequests --> media requests sent. `);\n } else {\n LoggerProxy.logger.info(\n `multistream:sendRequests --> detected duplicate WCME requests, skipping them... `\n );\n }\n }\n\n public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {\n // eslint-disable-next-line no-plusplus\n const newId = `${this.counter++}`;\n\n this.clientRequests[newId] = mediaRequest;\n\n const eventHandler = ({maxFs}) => {\n mediaRequest.preferredMaxFs = maxFs;\n this.debouncedSourceUpdateListener();\n };\n mediaRequest.handleMaxFs = eventHandler;\n\n mediaRequest.receiveSlots.forEach((rs) => {\n rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n rs.on(ReceiveSlotEvents.MaxFsUpdate, mediaRequest.handleMaxFs);\n });\n\n if (commit) {\n this.commit();\n }\n\n return newId;\n }\n\n public cancelRequest(requestId: MediaRequestId, commit = true) {\n const mediaRequest = this.clientRequests[requestId];\n\n mediaRequest?.receiveSlots.forEach((rs) => {\n rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n rs.off(ReceiveSlotEvents.MaxFsUpdate, mediaRequest.handleMaxFs);\n });\n\n delete this.clientRequests[requestId];\n\n if (commit) {\n this.commit();\n }\n }\n\n public commit() {\n return this.sendRequests();\n }\n\n public reset() {\n this.clientRequests = {};\n }\n}\n"],"mappings":"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"}
@@ -26,6 +26,9 @@ export interface MediaRequest {
26
26
  receiveSlots: Array<ReceiveSlot>;
27
27
  codecInfo?: CodecInfo;
28
28
  preferredMaxFs?: number;
29
+ handleMaxFs?: ({ maxFs }: {
30
+ maxFs: number;
31
+ }) => void;
29
32
  }
30
33
  export type MediaRequestId = string;
31
34
  type DegradationPreferences = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.140",
3
+ "version": "3.0.0-beta.142",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -32,12 +32,12 @@
32
32
  "build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
33
33
  },
34
34
  "devDependencies": {
35
- "@webex/plugin-meetings": "3.0.0-beta.140",
36
- "@webex/test-helper-chai": "3.0.0-beta.140",
37
- "@webex/test-helper-mocha": "3.0.0-beta.140",
38
- "@webex/test-helper-mock-webex": "3.0.0-beta.140",
39
- "@webex/test-helper-retry": "3.0.0-beta.140",
40
- "@webex/test-helper-test-users": "3.0.0-beta.140",
35
+ "@webex/plugin-meetings": "3.0.0-beta.142",
36
+ "@webex/test-helper-chai": "3.0.0-beta.142",
37
+ "@webex/test-helper-mocha": "3.0.0-beta.142",
38
+ "@webex/test-helper-mock-webex": "3.0.0-beta.142",
39
+ "@webex/test-helper-retry": "3.0.0-beta.142",
40
+ "@webex/test-helper-test-users": "3.0.0-beta.142",
41
41
  "chai": "^4.3.4",
42
42
  "chai-as-promised": "^7.1.1",
43
43
  "jsdom-global": "3.0.2",
@@ -46,19 +46,19 @@
46
46
  "typescript": "^4.7.4"
47
47
  },
48
48
  "dependencies": {
49
- "@webex/common": "3.0.0-beta.140",
50
- "@webex/internal-media-core": "1.38.2",
51
- "@webex/internal-plugin-conversation": "3.0.0-beta.140",
52
- "@webex/internal-plugin-device": "3.0.0-beta.140",
53
- "@webex/internal-plugin-llm": "3.0.0-beta.140",
54
- "@webex/internal-plugin-mercury": "3.0.0-beta.140",
55
- "@webex/internal-plugin-metrics": "3.0.0-beta.140",
56
- "@webex/internal-plugin-support": "3.0.0-beta.140",
57
- "@webex/internal-plugin-user": "3.0.0-beta.140",
58
- "@webex/media-helpers": "3.0.0-beta.140",
59
- "@webex/plugin-people": "3.0.0-beta.140",
60
- "@webex/plugin-rooms": "3.0.0-beta.140",
61
- "@webex/webex-core": "3.0.0-beta.140",
49
+ "@webex/common": "3.0.0-beta.142",
50
+ "@webex/internal-media-core": "1.38.3",
51
+ "@webex/internal-plugin-conversation": "3.0.0-beta.142",
52
+ "@webex/internal-plugin-device": "3.0.0-beta.142",
53
+ "@webex/internal-plugin-llm": "3.0.0-beta.142",
54
+ "@webex/internal-plugin-mercury": "3.0.0-beta.142",
55
+ "@webex/internal-plugin-metrics": "3.0.0-beta.142",
56
+ "@webex/internal-plugin-support": "3.0.0-beta.142",
57
+ "@webex/internal-plugin-user": "3.0.0-beta.142",
58
+ "@webex/media-helpers": "3.0.0-beta.142",
59
+ "@webex/plugin-people": "3.0.0-beta.142",
60
+ "@webex/plugin-rooms": "3.0.0-beta.142",
61
+ "@webex/webex-core": "3.0.0-beta.142",
62
62
  "ampersand-collection": "^2.0.2",
63
63
  "bowser": "^2.11.0",
64
64
  "btoa": "^1.2.1",
@@ -77,6 +77,22 @@ Media.getLocalMedia = (options: any, config: object) => {
77
77
  return Promise.resolve(undefined);
78
78
  };
79
79
 
80
+ Media.getDirection = (receive: boolean, send: boolean) => {
81
+ if (!receive && !send) {
82
+ return 'inactive';
83
+ }
84
+
85
+ if (receive && send) {
86
+ return 'sendrecv';
87
+ }
88
+
89
+ if (receive) {
90
+ return 'recvonly';
91
+ }
92
+
93
+ return 'sendonly';
94
+ };
95
+
80
96
  /**
81
97
  * creates a webrtc media connection with provided tracks and mediaDirection configuration
82
98
  *
@@ -180,17 +196,17 @@ Media.createMediaConnection = (
180
196
  },
181
197
  },
182
198
  {
183
- send: {
199
+ localTracks: {
184
200
  audio: audioTrack?.underlyingTrack,
185
201
  video: videoTrack?.underlyingTrack,
186
202
  screenShareVideo: shareTrack?.underlyingTrack,
187
203
  },
188
- receive: {
189
- audio: mediaDirection.receiveAudio,
190
- video: mediaDirection.receiveVideo,
191
- screenShareVideo: mediaDirection.receiveShare,
192
- remoteQualityLevel,
204
+ direction: {
205
+ audio: Media.getDirection(mediaDirection.receiveAudio, mediaDirection.sendAudio),
206
+ video: Media.getDirection(mediaDirection.receiveVideo, mediaDirection.sendVideo),
207
+ screenShareVideo: Media.getDirection(mediaDirection.receiveShare, mediaDirection.sendShare),
193
208
  },
209
+ remoteQualityLevel,
194
210
  },
195
211
  debugId
196
212
  );
@@ -5994,8 +5994,8 @@ export default class Meeting extends StatelessWebexPlugin {
5994
5994
  .then(() => this.preMedia(localStream, localShare, mediaSettings))
5995
5995
  .then(() =>
5996
5996
  this.mediaProperties.webrtcMediaConnection
5997
- .updateSendReceiveOptions({
5998
- send: {
5997
+ .update({
5998
+ localTracks: {
5999
5999
  audio: this.mediaProperties.mediaDirection.sendAudio
6000
6000
  ? this.mediaProperties.audioTrack.underlyingTrack
6001
6001
  : null,
@@ -6006,17 +6006,24 @@ export default class Meeting extends StatelessWebexPlugin {
6006
6006
  ? this.mediaProperties.shareTrack.underlyingTrack
6007
6007
  : null,
6008
6008
  },
6009
- receive: {
6010
- audio: this.mediaProperties.mediaDirection.receiveAudio,
6011
- video: this.mediaProperties.mediaDirection.receiveVideo,
6012
- screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
6013
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6009
+ direction: {
6010
+ audio: Media.getDirection(
6011
+ this.mediaProperties.mediaDirection.receiveAudio,
6012
+ this.mediaProperties.mediaDirection.sendAudio
6013
+ ),
6014
+ video: Media.getDirection(
6015
+ this.mediaProperties.mediaDirection.receiveVideo,
6016
+ this.mediaProperties.mediaDirection.sendVideo
6017
+ ),
6018
+ screenShareVideo: Media.getDirection(
6019
+ this.mediaProperties.mediaDirection.receiveShare,
6020
+ this.mediaProperties.mediaDirection.sendShare
6021
+ ),
6014
6022
  },
6023
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6015
6024
  })
6016
6025
  .then(() => {
6017
- LoggerProxy.logger.info(
6018
- `${LOG_HEADER} webrtcMediaConnection.updateSendReceiveOptions done`
6019
- );
6026
+ LoggerProxy.logger.info(`${LOG_HEADER} webrtcMediaConnection.update done`);
6020
6027
  })
6021
6028
  .catch((error) => {
6022
6029
  LoggerProxy.logger.error(`${LOG_HEADER} Error updatedMedia, `, error);
@@ -6096,14 +6103,20 @@ export default class Meeting extends StatelessWebexPlugin {
6096
6103
 
6097
6104
  return MeetingUtil.validateOptions({sendAudio, localStream: stream})
6098
6105
  .then(() =>
6099
- this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
6100
- send: {audio: track},
6101
- receive: {
6102
- audio: options.receiveAudio,
6103
- video: this.mediaProperties.mediaDirection.receiveVideo,
6104
- screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
6105
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6106
+ this.mediaProperties.webrtcMediaConnection.update({
6107
+ localTracks: {audio: track},
6108
+ direction: {
6109
+ audio: Media.getDirection(receiveAudio, sendAudio),
6110
+ video: Media.getDirection(
6111
+ this.mediaProperties.mediaDirection.receiveVideo,
6112
+ this.mediaProperties.mediaDirection.sendVideo
6113
+ ),
6114
+ screenShareVideo: Media.getDirection(
6115
+ this.mediaProperties.mediaDirection.receiveShare,
6116
+ this.mediaProperties.mediaDirection.sendShare
6117
+ ),
6106
6118
  },
6119
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6107
6120
  })
6108
6121
  )
6109
6122
  .then(() => {
@@ -6153,14 +6166,20 @@ export default class Meeting extends StatelessWebexPlugin {
6153
6166
 
6154
6167
  return MeetingUtil.validateOptions({sendVideo, localStream: stream})
6155
6168
  .then(() =>
6156
- this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
6157
- send: {video: track},
6158
- receive: {
6159
- audio: this.mediaProperties.mediaDirection.receiveAudio,
6160
- video: options.receiveVideo,
6161
- screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
6162
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6169
+ this.mediaProperties.webrtcMediaConnection.update({
6170
+ localTracks: {video: track},
6171
+ direction: {
6172
+ audio: Media.getDirection(
6173
+ this.mediaProperties.mediaDirection.receiveAudio,
6174
+ this.mediaProperties.mediaDirection.sendAudio
6175
+ ),
6176
+ video: Media.getDirection(receiveVideo, sendVideo),
6177
+ screenShareVideo: Media.getDirection(
6178
+ this.mediaProperties.mediaDirection.receiveShare,
6179
+ this.mediaProperties.mediaDirection.sendShare
6180
+ ),
6163
6181
  },
6182
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6164
6183
  })
6165
6184
  )
6166
6185
  .then(() => {
@@ -6241,14 +6260,20 @@ export default class Meeting extends StatelessWebexPlugin {
6241
6260
  .then(() => this.checkForStopShare(sendShare, previousSendShareStatus))
6242
6261
  .then((startShare) =>
6243
6262
  this.mediaProperties.webrtcMediaConnection
6244
- .updateSendReceiveOptions({
6245
- send: {screenShareVideo: track},
6246
- receive: {
6247
- audio: this.mediaProperties.mediaDirection.receiveAudio,
6248
- video: this.mediaProperties.mediaDirection.receiveVideo,
6249
- screenShareVideo: options.receiveShare,
6250
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6263
+ .update({
6264
+ localTracks: {screenShareVideo: track},
6265
+ direction: {
6266
+ audio: Media.getDirection(
6267
+ this.mediaProperties.mediaDirection.receiveAudio,
6268
+ this.mediaProperties.mediaDirection.sendAudio
6269
+ ),
6270
+ video: Media.getDirection(
6271
+ this.mediaProperties.mediaDirection.receiveVideo,
6272
+ this.mediaProperties.mediaDirection.sendVideo
6273
+ ),
6274
+ screenShareVideo: Media.getDirection(receiveShare, sendShare),
6251
6275
  },
6276
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
6252
6277
  })
6253
6278
  .then(() =>
6254
6279
  this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.LAMBDA, {
@@ -47,6 +47,7 @@ export interface MediaRequest {
47
47
  receiveSlots: Array<ReceiveSlot>;
48
48
  codecInfo?: CodecInfo;
49
49
  preferredMaxFs?: number;
50
+ handleMaxFs?: ({maxFs}: {maxFs: number}) => void;
50
51
  }
51
52
 
52
53
  export type MediaRequestId = string;
@@ -287,12 +288,15 @@ export class MediaRequestManager {
287
288
 
288
289
  this.clientRequests[newId] = mediaRequest;
289
290
 
291
+ const eventHandler = ({maxFs}) => {
292
+ mediaRequest.preferredMaxFs = maxFs;
293
+ this.debouncedSourceUpdateListener();
294
+ };
295
+ mediaRequest.handleMaxFs = eventHandler;
296
+
290
297
  mediaRequest.receiveSlots.forEach((rs) => {
291
298
  rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);
292
- rs.on(ReceiveSlotEvents.MaxFsUpdate, ({maxFs}) => {
293
- mediaRequest.preferredMaxFs = maxFs;
294
- this.debouncedSourceUpdateListener();
295
- });
299
+ rs.on(ReceiveSlotEvents.MaxFsUpdate, mediaRequest.handleMaxFs);
296
300
  });
297
301
 
298
302
  if (commit) {
@@ -303,8 +307,11 @@ export class MediaRequestManager {
303
307
  }
304
308
 
305
309
  public cancelRequest(requestId: MediaRequestId, commit = true) {
306
- this.clientRequests[requestId]?.receiveSlots.forEach((rs) => {
310
+ const mediaRequest = this.clientRequests[requestId];
311
+
312
+ mediaRequest?.receiveSlots.forEach((rs) => {
307
313
  rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);
314
+ rs.off(ReceiveSlotEvents.MaxFsUpdate, mediaRequest.handleMaxFs);
308
315
  });
309
316
 
310
317
  delete this.clientRequests[requestId];
@@ -35,10 +35,10 @@ describe('createMediaConnection', () => {
35
35
  Media.createMediaConnection(false, 'some debug id', {
36
36
  mediaProperties: {
37
37
  mediaDirection: {
38
- sendAudio: true,
38
+ sendAudio: false,
39
39
  sendVideo: true,
40
40
  sendShare: false,
41
- receiveAudio: true,
41
+ receiveAudio: false,
42
42
  receiveVideo: true,
43
43
  receiveShare: true,
44
44
  },
@@ -82,17 +82,17 @@ describe('createMediaConnection', () => {
82
82
  },
83
83
  },
84
84
  {
85
- send: {
85
+ localTracks: {
86
86
  audio: fakeAudioTrack.underlyingTrack,
87
87
  video: fakeVideoTrack.underlyingTrack,
88
88
  screenShareVideo: undefined,
89
89
  },
90
- receive: {
91
- audio: true,
92
- video: true,
93
- screenShareVideo: true,
94
- remoteQualityLevel: 'HIGH',
90
+ direction: {
91
+ audio: 'inactive',
92
+ video: 'sendrecv',
93
+ screenShareVideo: 'recvonly',
95
94
  },
95
+ remoteQualityLevel: 'HIGH',
96
96
  },
97
97
  'some debug id'
98
98
  );
@@ -208,7 +208,7 @@ describe('createMediaConnection', () => {
208
208
  const multistreamRoapMediaConnectionConstructorStub = sinon
209
209
  .stub(internalMediaModule, 'MultistreamRoapMediaConnection')
210
210
  .returns(fakeRoapMediaConnection);
211
-
211
+
212
212
  Media.createMediaConnection(true, 'debug string', {
213
213
  mediaProperties: {
214
214
  mediaDirection: {
@@ -285,17 +285,17 @@ describe('createMediaConnection', () => {
285
285
  },
286
286
  },
287
287
  {
288
- send: {
288
+ localTracks: {
289
289
  audio: fakeAudioTrack.underlyingTrack,
290
290
  video: undefined,
291
291
  screenShareVideo: fakeVideoTrack.underlyingTrack,
292
292
  },
293
- receive: {
294
- audio: true,
295
- video: true,
296
- screenShareVideo: true,
297
- remoteQualityLevel: 'HIGH',
293
+ direction: {
294
+ audio: 'sendrecv',
295
+ video: 'sendrecv',
296
+ screenShareVideo: 'sendrecv',
298
297
  },
298
+ remoteQualityLevel: 'HIGH',
299
299
  },
300
300
  'some debug id'
301
301
  );
@@ -2313,11 +2313,11 @@ describe('plugin-meetings', () => {
2313
2313
  receiveShare: true,
2314
2314
  };
2315
2315
  meeting.mediaProperties.webrtcMediaConnection = {
2316
- updateSendReceiveOptions: sinon.stub(),
2316
+ update: sinon.stub(),
2317
2317
  };
2318
2318
  sinon.stub(MeetingUtil, 'getTrack').returns({audioTrack: FAKE_AUDIO_TRACK});
2319
2319
  });
2320
- it('calls this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions', () =>
2320
+ it('calls this.mediaProperties.webrtcMediaConnection.update', () =>
2321
2321
  meeting
2322
2322
  .updateAudio({
2323
2323
  sendAudio: true,
@@ -2326,18 +2326,18 @@ describe('plugin-meetings', () => {
2326
2326
  })
2327
2327
  .then(() => {
2328
2328
  assert.calledOnce(
2329
- meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions
2329
+ meeting.mediaProperties.webrtcMediaConnection.update
2330
2330
  );
2331
2331
  assert.calledWith(
2332
- meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions,
2332
+ meeting.mediaProperties.webrtcMediaConnection.update,
2333
2333
  {
2334
- send: {audio: FAKE_AUDIO_TRACK},
2335
- receive: {
2336
- audio: true,
2337
- video: true,
2338
- screenShareVideo: true,
2339
- remoteQualityLevel: 'HIGH',
2334
+ localTracks: {audio: FAKE_AUDIO_TRACK},
2335
+ direction: {
2336
+ audio: 'sendrecv',
2337
+ video: 'sendrecv',
2338
+ screenShareVideo: 'recvonly',
2340
2339
  },
2340
+ remoteQualityLevel: 'HIGH',
2341
2341
  }
2342
2342
  );
2343
2343
  }));
@@ -2481,7 +2481,7 @@ describe('plugin-meetings', () => {
2481
2481
 
2482
2482
  sandbox.stub(meeting, 'canUpdateMedia').returns(false);
2483
2483
  meeting.mediaProperties.webrtcMediaConnection = {
2484
- updateSendReceiveOptions: sinon.stub().resolves({}),
2484
+ update: sinon.stub().resolves({}),
2485
2485
  };
2486
2486
 
2487
2487
  let myPromiseResolved = false;
@@ -2497,7 +2497,7 @@ describe('plugin-meetings', () => {
2497
2497
  });
2498
2498
 
2499
2499
  // verify that nothing was done
2500
- assert.notCalled(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
2500
+ assert.notCalled(meeting.mediaProperties.webrtcMediaConnection.update);
2501
2501
 
2502
2502
  // now trigger processing of the queue
2503
2503
  meeting.canUpdateMedia.restore();
@@ -2506,22 +2506,22 @@ describe('plugin-meetings', () => {
2506
2506
  meeting.processNextQueuedMediaUpdate();
2507
2507
  await testUtils.flushPromises();
2508
2508
 
2509
- // and check that updateSendReceiveOptions is called with the original args
2510
- assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
2509
+ // and check that update is called with the original args
2510
+ assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.update);
2511
2511
  assert.calledWith(
2512
- meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions,
2512
+ meeting.mediaProperties.webrtcMediaConnection.update,
2513
2513
  {
2514
- send: {
2514
+ localTracks: {
2515
2515
  audio: FAKE_TRACKS.audio,
2516
2516
  video: FAKE_TRACKS.video,
2517
2517
  screenShareVideo: FAKE_TRACKS.screenshareVideo,
2518
2518
  },
2519
- receive: {
2520
- audio: true,
2521
- video: true,
2522
- screenShareVideo: true,
2523
- remoteQualityLevel: 'HIGH',
2519
+ direction: {
2520
+ audio: 'sendrecv',
2521
+ video: 'sendrecv',
2522
+ screenShareVideo: 'sendrecv',
2524
2523
  },
2524
+ remoteQualityLevel: 'HIGH',
2525
2525
  }
2526
2526
  );
2527
2527
  assert.isTrue(myPromiseResolved);
@@ -2544,8 +2544,8 @@ describe('plugin-meetings', () => {
2544
2544
  eventListeners[event] = listener;
2545
2545
  }),
2546
2546
 
2547
- updateSendReceiveOptions: sinon.stub().callsFake(() => {
2548
- // trigger ROAP_STARTED before updateSendReceiveOptions() resolves
2547
+ update: sinon.stub().callsFake(() => {
2548
+ // trigger ROAP_STARTED before update() resolves
2549
2549
  if (eventListeners[Event.ROAP_STARTED]) {
2550
2550
  eventListeners[Event.ROAP_STARTED]();
2551
2551
  } else {
@@ -2583,7 +2583,7 @@ describe('plugin-meetings', () => {
2583
2583
 
2584
2584
  await testUtils.flushPromises();
2585
2585
 
2586
- assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
2586
+ assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.update);
2587
2587
  assert.isFalse(myPromiseResolved);
2588
2588
 
2589
2589
  // verify that requestScreenShareFloorStub was not called yet
@@ -2636,8 +2636,8 @@ describe('plugin-meetings', () => {
2636
2636
  eventListeners[event] = listener;
2637
2637
  }),
2638
2638
 
2639
- updateSendReceiveOptions: sinon.stub().callsFake(() => {
2640
- // trigger ROAP_STARTED before updateSendReceiveOptions() resolves
2639
+ update: sinon.stub().callsFake(() => {
2640
+ // trigger ROAP_STARTED before update() resolves
2641
2641
  if (eventListeners[Event.ROAP_STARTED]) {
2642
2642
  eventListeners[Event.ROAP_STARTED]();
2643
2643
  } else {
@@ -2678,7 +2678,7 @@ describe('plugin-meetings', () => {
2678
2678
 
2679
2679
  await testUtils.flushPromises();
2680
2680
 
2681
- assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
2681
+ assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.update);
2682
2682
  assert.isFalse(myPromiseResolved);
2683
2683
 
2684
2684
  // verify that requestScreenShareFloorStub was not called yet
@@ -2694,8 +2694,8 @@ describe('plugin-meetings', () => {
2694
2694
  it('when changing screen share stream and no roap transaction happening, it requests floor immediately', async () => {
2695
2695
  let myPromiseResolved = false;
2696
2696
 
2697
- // simulate a case when no roap transaction is triggered by updateSendReceiveOptions
2698
- meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions = sinon
2697
+ // simulate a case when no roap transaction is triggered by update
2698
+ meeting.mediaProperties.webrtcMediaConnection.update = sinon
2699
2699
  .stub()
2700
2700
  .resolves({});
2701
2701
 
@@ -2711,7 +2711,7 @@ describe('plugin-meetings', () => {
2711
2711
 
2712
2712
  await testUtils.flushPromises();
2713
2713
 
2714
- assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
2714
+ assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.update);
2715
2715
  assert.calledOnce(requestScreenShareFloorStub);
2716
2716
  assert.isTrue(myPromiseResolved);
2717
2717
  });