@webex/plugin-meetings 3.0.0-beta.403 → 3.0.0-beta.404
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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/types/multistream/mediaRequestManager.d.ts +1 -2
- package/dist/types/multistream/remoteMediaGroup.d.ts +1 -1
- package/dist/types/multistream/remoteMediaManager.d.ts +1 -2
- package/dist/types/multistream/sendSlotManager.d.ts +1 -2
- package/dist/webinar/index.js +1 -1
- package/package.json +20 -20
- package/src/multistream/mediaRequestManager.ts +1 -1
- package/src/multistream/remoteMediaGroup.ts +1 -1
- package/src/multistream/remoteMediaManager.ts +1 -2
- package/src/multistream/sendSlotManager.ts +1 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +0 -1
- package/test/unit/spec/multistream/remoteMediaManager.ts +0 -1
package/dist/breakouts/index.js
CHANGED
|
@@ -1041,7 +1041,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
|
|
|
1041
1041
|
this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
|
|
1042
1042
|
}
|
|
1043
1043
|
},
|
|
1044
|
-
version: "3.0.0-beta.
|
|
1044
|
+
version: "3.0.0-beta.404"
|
|
1045
1045
|
});
|
|
1046
1046
|
var _default = Breakouts;
|
|
1047
1047
|
exports.default = _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","DEBOUNCED_SOURCE_UPDATE_TIME","MediaRequestManager","sendMediaRequestsCallback","options","counter","numLiveSources","numTotalSources","clientRequests","degradationPreferences","kind","trimRequestsToNumOfSources","sourceUpdateListener","commit","bind","debouncedSourceUpdateListener","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","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","preferLiveVideo","getPreferLiveVideo","undefined","numStreamsAvailable","sort","a","b","policyInfo","policy","priority","request","trimmedCount","Error","value","key","streamRequests","cloneClientRequests","trimRequests","getDegradedClientRequests","push","StreamRequest","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","crossPriorityDuplication","crossPolicyDuplication","namedMediaGroups","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 {cloneDeepWith, debounce, isEmpty} from 'lodash';\n\nimport {NamedMediaGroup} from '@webex/json-multistream';\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 namedMediaGroups?: NamedMediaGroup[];\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 trimRequestsToNumOfSources: boolean; // if enabled, AS speaker requests will be trimmed based on the calls to setNumCurrentSources()\n};\n\ntype ClientRequestsMap = {[key: MediaRequestId]: MediaRequest};\n\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private kind: Kind;\n\n private counter: number;\n\n private clientRequests: ClientRequestsMap;\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n private debouncedSourceUpdateListener: () => void;\n\n private previousStreamRequests: Array<StreamRequest> = [];\n\n private trimRequestsToNumOfSources: boolean;\n private numTotalSources: number;\n private numLiveSources: number;\n\n constructor(sendMediaRequestsCallback: SendMediaRequestsCallback, options: Options) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.numLiveSources = 0;\n this.numTotalSources = 0;\n this.clientRequests = {};\n this.degradationPreferences = options.degradationPreferences;\n this.kind = options.kind;\n this.trimRequestsToNumOfSources = options.trimRequestsToNumOfSources;\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(clientRequests: ClientRequestsMap) {\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.values(clientRequests).forEach((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 = mr.receiveSlots.filter((rs) => rs.sourceState === 'live');\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\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 /** Modifies the passed in clientRequests and makes sure that in total they don't ask\n * for more streams than there are available.\n *\n * @param {Object} clientRequests\n * @returns {void}\n */\n private trimRequests(clientRequests: ClientRequestsMap) {\n const preferLiveVideo = this.getPreferLiveVideo();\n\n if (!this.trimRequestsToNumOfSources) {\n return;\n }\n\n // preferLiveVideo being undefined means that there are no active-speaker requests so we don't need to do any trimming\n if (preferLiveVideo === undefined) {\n return;\n }\n\n let numStreamsAvailable = preferLiveVideo ? this.numLiveSources : this.numTotalSources;\n\n Object.values(clientRequests)\n .sort((a, b) => {\n // we have to count how many streams we're asking for\n // and should not ask for more than numStreamsAvailable in total,\n // so we might need to trim active-speaker requests and first ones to trim should be\n // the ones with lowest priority\n\n // receiver-selected requests have priority over active-speakers\n if (a.policyInfo.policy === 'receiver-selected') {\n return -1;\n }\n if (b.policyInfo.policy === 'receiver-selected') {\n return 1;\n }\n\n // and active-speakers are sorted by descending priority\n return b.policyInfo.priority - a.policyInfo.priority;\n })\n .forEach((request) => {\n // we only trim active-speaker requests\n if (request.policyInfo.policy === 'active-speaker') {\n const trimmedCount = Math.min(numStreamsAvailable, request.receiveSlots.length);\n\n request.receiveSlots.length = trimmedCount;\n\n numStreamsAvailable -= trimmedCount;\n } else {\n numStreamsAvailable -= request.receiveSlots.length;\n }\n\n if (numStreamsAvailable < 0) {\n numStreamsAvailable = 0;\n }\n });\n }\n\n private getPreferLiveVideo(): boolean | undefined {\n let preferLiveVideo;\n\n Object.values(this.clientRequests).forEach((mr) => {\n if (mr.policyInfo.policy === 'active-speaker') {\n // take the value from first encountered active speaker request\n if (preferLiveVideo === undefined) {\n preferLiveVideo = mr.policyInfo.preferLiveVideo;\n }\n\n if (mr.policyInfo.preferLiveVideo !== preferLiveVideo) {\n throw new Error(\n 'a mix of active-speaker groups with different values for preferLiveVideo is not supported'\n );\n }\n }\n });\n\n return preferLiveVideo;\n }\n\n private cloneClientRequests(): ClientRequestsMap {\n // we clone the client requests but without cloning the ReceiveSlots that they reference\n return cloneDeepWith(this.clientRequests, (value, key) => {\n if (key === 'receiveSlots') {\n return [...value];\n }\n\n return undefined;\n });\n }\n\n private sendRequests() {\n const streamRequests: StreamRequest[] = [];\n\n // clone the requests so that any modifications we do to them don't affect the original ones\n const clientRequests = this.cloneClientRequests();\n\n this.trimRequests(clientRequests);\n this.getDegradedClientRequests(clientRequests);\n\n // map all the client media requests to wcme stream requests\n Object.values(clientRequests).forEach((mr) => {\n if (mr.receiveSlots.length > 0) {\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 mr.policyInfo.namedMediaGroups\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\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 this.numTotalSources = 0;\n this.numLiveSources = 0;\n }\n\n public setNumCurrentSources(numTotalSources: number, numLiveSources: number) {\n this.numTotalSources = numTotalSources;\n this.numLiveSources = numLiveSources;\n\n this.sendRequests();\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","numLiveSources","numTotalSources","clientRequests","degradationPreferences","kind","trimRequestsToNumOfSources","sourceUpdateListener","commit","bind","debouncedSourceUpdateListener","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","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","preferLiveVideo","getPreferLiveVideo","undefined","numStreamsAvailable","sort","a","b","policyInfo","policy","priority","request","trimmedCount","Error","value","key","streamRequests","cloneClientRequests","trimRequests","getDegradedClientRequests","push","StreamRequest","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","crossPriorityDuplication","crossPolicyDuplication","namedMediaGroups","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 NamedMediaGroup,\n} from '@webex/internal-media-core';\nimport {cloneDeepWith, 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 namedMediaGroups?: NamedMediaGroup[];\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 trimRequestsToNumOfSources: boolean; // if enabled, AS speaker requests will be trimmed based on the calls to setNumCurrentSources()\n};\n\ntype ClientRequestsMap = {[key: MediaRequestId]: MediaRequest};\n\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private kind: Kind;\n\n private counter: number;\n\n private clientRequests: ClientRequestsMap;\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n private debouncedSourceUpdateListener: () => void;\n\n private previousStreamRequests: Array<StreamRequest> = [];\n\n private trimRequestsToNumOfSources: boolean;\n private numTotalSources: number;\n private numLiveSources: number;\n\n constructor(sendMediaRequestsCallback: SendMediaRequestsCallback, options: Options) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.numLiveSources = 0;\n this.numTotalSources = 0;\n this.clientRequests = {};\n this.degradationPreferences = options.degradationPreferences;\n this.kind = options.kind;\n this.trimRequestsToNumOfSources = options.trimRequestsToNumOfSources;\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(clientRequests: ClientRequestsMap) {\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.values(clientRequests).forEach((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 = mr.receiveSlots.filter((rs) => rs.sourceState === 'live');\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\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 /** Modifies the passed in clientRequests and makes sure that in total they don't ask\n * for more streams than there are available.\n *\n * @param {Object} clientRequests\n * @returns {void}\n */\n private trimRequests(clientRequests: ClientRequestsMap) {\n const preferLiveVideo = this.getPreferLiveVideo();\n\n if (!this.trimRequestsToNumOfSources) {\n return;\n }\n\n // preferLiveVideo being undefined means that there are no active-speaker requests so we don't need to do any trimming\n if (preferLiveVideo === undefined) {\n return;\n }\n\n let numStreamsAvailable = preferLiveVideo ? this.numLiveSources : this.numTotalSources;\n\n Object.values(clientRequests)\n .sort((a, b) => {\n // we have to count how many streams we're asking for\n // and should not ask for more than numStreamsAvailable in total,\n // so we might need to trim active-speaker requests and first ones to trim should be\n // the ones with lowest priority\n\n // receiver-selected requests have priority over active-speakers\n if (a.policyInfo.policy === 'receiver-selected') {\n return -1;\n }\n if (b.policyInfo.policy === 'receiver-selected') {\n return 1;\n }\n\n // and active-speakers are sorted by descending priority\n return b.policyInfo.priority - a.policyInfo.priority;\n })\n .forEach((request) => {\n // we only trim active-speaker requests\n if (request.policyInfo.policy === 'active-speaker') {\n const trimmedCount = Math.min(numStreamsAvailable, request.receiveSlots.length);\n\n request.receiveSlots.length = trimmedCount;\n\n numStreamsAvailable -= trimmedCount;\n } else {\n numStreamsAvailable -= request.receiveSlots.length;\n }\n\n if (numStreamsAvailable < 0) {\n numStreamsAvailable = 0;\n }\n });\n }\n\n private getPreferLiveVideo(): boolean | undefined {\n let preferLiveVideo;\n\n Object.values(this.clientRequests).forEach((mr) => {\n if (mr.policyInfo.policy === 'active-speaker') {\n // take the value from first encountered active speaker request\n if (preferLiveVideo === undefined) {\n preferLiveVideo = mr.policyInfo.preferLiveVideo;\n }\n\n if (mr.policyInfo.preferLiveVideo !== preferLiveVideo) {\n throw new Error(\n 'a mix of active-speaker groups with different values for preferLiveVideo is not supported'\n );\n }\n }\n });\n\n return preferLiveVideo;\n }\n\n private cloneClientRequests(): ClientRequestsMap {\n // we clone the client requests but without cloning the ReceiveSlots that they reference\n return cloneDeepWith(this.clientRequests, (value, key) => {\n if (key === 'receiveSlots') {\n return [...value];\n }\n\n return undefined;\n });\n }\n\n private sendRequests() {\n const streamRequests: StreamRequest[] = [];\n\n // clone the requests so that any modifications we do to them don't affect the original ones\n const clientRequests = this.cloneClientRequests();\n\n this.trimRequests(clientRequests);\n this.getDegradedClientRequests(clientRequests);\n\n // map all the client media requests to wcme stream requests\n Object.values(clientRequests).forEach((mr) => {\n if (mr.receiveSlots.length > 0) {\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 mr.policyInfo.namedMediaGroups\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\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 this.numTotalSources = 0;\n this.numLiveSources = 0;\n }\n\n public setNumCurrentSources(numTotalSources: number, numLiveSources: number) {\n this.numTotalSources = numTotalSources;\n this.numLiveSources = numLiveSources;\n\n this.sendRequests();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AACA;AAaA;AAEA;AACA;AAjBA;;AAwDA,IAAMA,cAAc,GAAG;EACrBC,IAAI,EAAE;IACJC,KAAK,EAAE,IAAI;IACXC,MAAM,EAAE,IAAI;IACZC,OAAO,EAAE;EACX;AACF,CAAC;AAED,IAAMC,4BAA4B,GAAG,IAAI;AAAC,IAiB7BC,mBAAmB;EAqB9B,6BAAYC,yBAAoD,EAAEC,OAAgB,EAAE;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA,8DAN7B,EAAE;IAAA;IAAA;IAAA;IAOvD,IAAI,CAACD,yBAAyB,GAAGA,yBAAyB;IAC1D,IAAI,CAACE,OAAO,GAAG,CAAC;IAChB,IAAI,CAACC,cAAc,GAAG,CAAC;IACvB,IAAI,CAACC,eAAe,GAAG,CAAC;IACxB,IAAI,CAACC,cAAc,GAAG,CAAC,CAAC;IACxB,IAAI,CAACC,sBAAsB,GAAGL,OAAO,CAACK,sBAAsB;IAC5D,IAAI,CAACC,IAAI,GAAGN,OAAO,CAACM,IAAI;IACxB,IAAI,CAACC,0BAA0B,GAAGP,OAAO,CAACO,0BAA0B;IACpE,IAAI,CAACC,oBAAoB,GAAG,IAAI,CAACC,MAAM,CAACC,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACC,6BAA6B,GAAG,wBACnC,IAAI,CAACH,oBAAoB,EACzBX,4BAA4B,CAC7B;EACH;EAAC;IAAA;IAAA,OAED,mCAAiCQ,sBAA8C,EAAE;MAC/E,IAAI,CAACA,sBAAsB,GAAGA,sBAAsB;MACpD,IAAI,CAACO,YAAY,EAAE,CAAC,CAAC;IACvB;EAAC;IAAA;IAAA,OAED,mCAAkCR,cAAiC,EAAE;MAAA;MACnE,IAAMS,WAAW,GAAG,CAClB,IAAAC,qBAAQ,EAAC,MAAM,CAAC,EAChB,IAAAA,qBAAQ,EAAC,OAAO,CAAC,EACjB,IAAAA,qBAAQ,EAAC,QAAQ,CAAC,EAClB,IAAAA,qBAAQ,EAAC,OAAO,CAAC,EACjB,IAAAA,qBAAQ,EAAC,YAAY,CAAC,EACtB,IAAAA,qBAAQ,EAAC,WAAW,CAAC,CACtB;;MAED;MAAA,8BACgD;QAC9C,IAAIC,yBAAyB,GAAG,CAAC;QACjC,qBAAcX,cAAc,CAAC,CAACY,OAAO,CAAC,UAACC,EAAE,EAAK;UAC5C,IAAIA,EAAE,CAACC,SAAS,EAAE;YAChBD,EAAE,CAACC,SAAS,CAACxB,KAAK,GAAGyB,IAAI,CAACC,GAAG,CAC3BH,EAAE,CAACI,cAAc,IAAI7B,cAAc,CAACC,IAAI,CAACC,KAAK,EAC9CuB,EAAE,CAACC,SAAS,CAACxB,KAAK,IAAIF,cAAc,CAACC,IAAI,CAACC,KAAK,EAC/CmB,WAAW,CAACS,CAAC,CAAC,CACf;YACD;YACA,IAAMC,mBAAmB,GAAGN,EAAE,CAACO,YAAY,CAACC,MAAM,CAAC,UAACC,EAAE;cAAA,OAAKA,EAAE,CAACC,WAAW,KAAK,MAAM;YAAA,EAAC;YACrFZ,yBAAyB,IAAIE,EAAE,CAACC,SAAS,CAACxB,KAAK,GAAG6B,mBAAmB,CAACK,MAAM;UAC9E;QACF,CAAC,CAAC;QACF,IAAIb,yBAAyB,IAAI,KAAI,CAACV,sBAAsB,CAACwB,mBAAmB,EAAE;UAChF,IAAIP,CAAC,KAAK,CAAC,EAAE;YACXQ,oBAAW,CAACC,MAAM,CAACC,IAAI,gHACmFnB,WAAW,CAACS,CAAC,CAAC,EACvH;UACH;UAAC;QAEH,CAAC,MAAM,IAAIA,CAAC,KAAKT,WAAW,CAACe,MAAM,GAAG,CAAC,EAAE;UACvCE,oBAAW,CAACC,MAAM,CAACC,IAAI,+EACkDnB,WAAW,CAACS,CAAC,CAAC,0FACtF;QACH;MACF,CAAC;MA1BD,KAAK,IAAIA,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGT,WAAW,CAACe,MAAM,EAAEN,CAAC,IAAI,CAAC;QAAA;QAAA,sBAoB1C;MAAM;IAOZ;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;IACE;EAAA;IAAA;IAAA,OACA,iBAAeW,cAA6B,EAAEC,cAA6B,EAAE;MAC3E,OACE,wBAAeD,cAAc,CAACE,mBAAmB,EAAE,CAAC,KACpD,wBAAeD,cAAc,CAACC,mBAAmB,EAAE,CAAC;IAExD;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,uCAAsCC,WAA4B,EAAE;MAAA;MAClE,OACE,CAAC,uBAAQ,IAAI,CAACC,sBAAsB,CAAC,IACrC,IAAI,CAACA,sBAAsB,CAACT,MAAM,KAAKQ,WAAW,CAACR,MAAM,IACzD,IAAI,CAACS,sBAAsB,CAACC,KAAK,CAAC,UAACC,GAAG,EAAEC,GAAG;QAAA,OAAK,MAAI,CAACC,OAAO,CAACF,GAAG,EAAEH,WAAW,CAACI,GAAG,CAAC,CAAC;MAAA,EAAC;IAExF;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EATE;IAAA;IAAA,OAUA,oCAAmCE,YAA0B,EAAU;MACrE,IAAI,IAAI,CAACpC,IAAI,KAAK,OAAO,EAAE;QACzB;QACA,OAAOqC,0CAAuB,CAACC,aAAa;MAC9C;MAEA,OAAO,IAAAC,uDAAoC,EACzCH,YAAY,CAACxB,SAAS,CAACxB,KAAK,IAAIF,cAAc,CAACC,IAAI,CAACC,KAAK,CAC1D;IACH;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;IACE;EAAA;IAAA;IAAA,OACA,wBAAuBgD,YAA0B,EAAU;MACzD;MACA,IAAM/C,MAAM,GAAG+C,YAAY,CAACxB,SAAS,CAACvB,MAAM,IAAIH,cAAc,CAACC,IAAI,CAACE,MAAM;;MAE1E;MACA,OAAQ+C,YAAY,CAACxB,SAAS,CAACxB,KAAK,GAAGC,MAAM,GAAI,GAAG;IACtD;;IAEA;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA,OAKA,iCAAqC;MACnC,IAAI,CAAC0C,sBAAsB,GAAG,EAAE;IAClC;;IAEA;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA,OAMA,sBAAqBjC,cAAiC,EAAE;MACtD,IAAM0C,eAAe,GAAG,IAAI,CAACC,kBAAkB,EAAE;MAEjD,IAAI,CAAC,IAAI,CAACxC,0BAA0B,EAAE;QACpC;MACF;;MAEA;MACA,IAAIuC,eAAe,KAAKE,SAAS,EAAE;QACjC;MACF;MAEA,IAAIC,mBAAmB,GAAGH,eAAe,GAAG,IAAI,CAAC5C,cAAc,GAAG,IAAI,CAACC,eAAe;MAEtF,qBAAcC,cAAc,CAAC,CAC1B8C,IAAI,CAAC,UAACC,CAAC,EAAEC,CAAC,EAAK;QACd;QACA;QACA;QACA;;QAEA;QACA,IAAID,CAAC,CAACE,UAAU,CAACC,MAAM,KAAK,mBAAmB,EAAE;UAC/C,OAAO,CAAC,CAAC;QACX;QACA,IAAIF,CAAC,CAACC,UAAU,CAACC,MAAM,KAAK,mBAAmB,EAAE;UAC/C,OAAO,CAAC;QACV;;QAEA;QACA,OAAOF,CAAC,CAACC,UAAU,CAACE,QAAQ,GAAGJ,CAAC,CAACE,UAAU,CAACE,QAAQ;MACtD,CAAC,CAAC,CACDvC,OAAO,CAAC,UAACwC,OAAO,EAAK;QACpB;QACA,IAAIA,OAAO,CAACH,UAAU,CAACC,MAAM,KAAK,gBAAgB,EAAE;UAClD,IAAMG,YAAY,GAAGtC,IAAI,CAACC,GAAG,CAAC6B,mBAAmB,EAAEO,OAAO,CAAChC,YAAY,CAACI,MAAM,CAAC;UAE/E4B,OAAO,CAAChC,YAAY,CAACI,MAAM,GAAG6B,YAAY;UAE1CR,mBAAmB,IAAIQ,YAAY;QACrC,CAAC,MAAM;UACLR,mBAAmB,IAAIO,OAAO,CAAChC,YAAY,CAACI,MAAM;QACpD;QAEA,IAAIqB,mBAAmB,GAAG,CAAC,EAAE;UAC3BA,mBAAmB,GAAG,CAAC;QACzB;MACF,CAAC,CAAC;IACN;EAAC;IAAA;IAAA,OAED,8BAAkD;MAChD,IAAIH,eAAe;MAEnB,qBAAc,IAAI,CAAC1C,cAAc,CAAC,CAACY,OAAO,CAAC,UAACC,EAAE,EAAK;QACjD,IAAIA,EAAE,CAACoC,UAAU,CAACC,MAAM,KAAK,gBAAgB,EAAE;UAC7C;UACA,IAAIR,eAAe,KAAKE,SAAS,EAAE;YACjCF,eAAe,GAAG7B,EAAE,CAACoC,UAAU,CAACP,eAAe;UACjD;UAEA,IAAI7B,EAAE,CAACoC,UAAU,CAACP,eAAe,KAAKA,eAAe,EAAE;YACrD,MAAM,IAAIY,KAAK,CACb,2FAA2F,CAC5F;UACH;QACF;MACF,CAAC,CAAC;MAEF,OAAOZ,eAAe;IACxB;EAAC;IAAA;IAAA,OAED,+BAAiD;MAC/C;MACA,OAAO,6BAAc,IAAI,CAAC1C,cAAc,EAAE,UAACuD,KAAK,EAAEC,GAAG,EAAK;QACxD,IAAIA,GAAG,KAAK,cAAc,EAAE;UAC1B,wCAAWD,KAAK;QAClB;QAEA,OAAOX,SAAS;MAClB,CAAC,CAAC;IACJ;EAAC;IAAA;IAAA,OAED,wBAAuB;MAAA;MACrB,IAAMa,cAA+B,GAAG,EAAE;;MAE1C;MACA,IAAMzD,cAAc,GAAG,IAAI,CAAC0D,mBAAmB,EAAE;MAEjD,IAAI,CAACC,YAAY,CAAC3D,cAAc,CAAC;MACjC,IAAI,CAAC4D,yBAAyB,CAAC5D,cAAc,CAAC;;MAE9C;MACA,qBAAcA,cAAc,CAAC,CAACY,OAAO,CAAC,UAACC,EAAE,EAAK;QAC5C,IAAIA,EAAE,CAACO,YAAY,CAACI,MAAM,GAAG,CAAC,EAAE;UAC9BiC,cAAc,CAACI,IAAI,CACjB,IAAIC,gCAAa,CACfjD,EAAE,CAACoC,UAAU,CAACC,MAAM,KAAK,gBAAgB,GACrCa,yBAAM,CAACC,aAAa,GACpBD,yBAAM,CAACE,gBAAgB,EAC3BpD,EAAE,CAACoC,UAAU,CAACC,MAAM,KAAK,gBAAgB,GACrC,IAAIgB,oCAAiB,CACnBrD,EAAE,CAACoC,UAAU,CAACE,QAAQ,EACtBtC,EAAE,CAACoC,UAAU,CAACkB,wBAAwB,EACtCtD,EAAE,CAACoC,UAAU,CAACmB,sBAAsB,EACpCvD,EAAE,CAACoC,UAAU,CAACP,eAAe,EAC7B7B,EAAE,CAACoC,UAAU,CAACoB,gBAAgB,CAC/B,GACD,IAAIC,uCAAoB,CAACzD,EAAE,CAACoC,UAAU,CAACsB,GAAG,CAAC,EAC/C1D,EAAE,CAACO,YAAY,CAACoD,GAAG,CAAC,UAACC,WAAW;YAAA,OAAKA,WAAW,CAACC,eAAe;UAAA,EAAC,EACjE,MAAI,CAACC,0BAA0B,CAAC9D,EAAE,CAAC,EACnCA,EAAE,CAACC,SAAS,IAAI,CACd,IAAI8D,4BAAa,CACf,IAAI,EACJ,IAAIC,4BAAS,CACXhE,EAAE,CAACC,SAAS,CAACxB,KAAK,EAClBuB,EAAE,CAACC,SAAS,CAACvB,MAAM,IAAIH,cAAc,CAACC,IAAI,CAACE,MAAM,EACjD,MAAI,CAACuF,cAAc,CAACjE,EAAE,CAAC,EACvBA,EAAE,CAACC,SAAS,CAACiE,QAAQ,EACrBlE,EAAE,CAACC,SAAS,CAACkE,SAAS,CACvB,CACF,CACF,CACF,CACF;QACH;MACF,CAAC,CAAC;;MAEF;MACA;MACA,IAAI,CAAC,IAAI,CAACC,6BAA6B,CAACxB,cAAc,CAAC,EAAE;QACvD,IAAI,CAAC9D,yBAAyB,CAAC8D,cAAc,CAAC;QAC9C,IAAI,CAACxB,sBAAsB,GAAGwB,cAAc;QAC5C/B,oBAAW,CAACC,MAAM,CAACuD,IAAI,sDAAsD;MAC/E,CAAC,MAAM;QACLxD,oBAAW,CAACC,MAAM,CAACuD,IAAI,oFAEtB;MACH;IACF;EAAC;IAAA;IAAA,OAED,oBAAkB5C,YAA0B,EAAiC;MAAA;MAAA,IAA/BjC,MAAM,uEAAG,IAAI;MACzD;MACA,IAAM8E,KAAK,aAAM,IAAI,CAACtF,OAAO,EAAE,CAAE;MAEjC,IAAI,CAACG,cAAc,CAACmF,KAAK,CAAC,GAAG7C,YAAY;MAEzC,IAAM8C,YAAY,GAAG,SAAfA,YAAY,OAAgB;QAAA,IAAX9F,KAAK,QAALA,KAAK;QAC1BgD,YAAY,CAACrB,cAAc,GAAG3B,KAAK;QACnC,MAAI,CAACiB,6BAA6B,EAAE;MACtC,CAAC;MACD+B,YAAY,CAAC+C,WAAW,GAAGD,YAAY;MAEvC9C,YAAY,CAAClB,YAAY,CAACR,OAAO,CAAC,UAACU,EAAE,EAAK;QACxCA,EAAE,CAACgE,EAAE,CAACC,8BAAiB,CAACC,YAAY,EAAE,MAAI,CAACpF,oBAAoB,CAAC;QAChEkB,EAAE,CAACgE,EAAE,CAACC,8BAAiB,CAACE,WAAW,EAAEnD,YAAY,CAAC+C,WAAW,CAAC;MAChE,CAAC,CAAC;MAEF,IAAIhF,MAAM,EAAE;QACV,IAAI,CAACA,MAAM,EAAE;MACf;MAEA,OAAO8E,KAAK;IACd;EAAC;IAAA;IAAA,OAED,uBAAqBO,SAAyB,EAAiB;MAAA;MAAA,IAAfrF,MAAM,uEAAG,IAAI;MAC3D,IAAMiC,YAAY,GAAG,IAAI,CAACtC,cAAc,CAAC0F,SAAS,CAAC;MAEnDpD,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAElB,YAAY,CAACR,OAAO,CAAC,UAACU,EAAE,EAAK;QACzCA,EAAE,CAACqE,GAAG,CAACJ,8BAAiB,CAACC,YAAY,EAAE,MAAI,CAACpF,oBAAoB,CAAC;QACjEkB,EAAE,CAACqE,GAAG,CAACJ,8BAAiB,CAACE,WAAW,EAAEnD,YAAY,CAAC+C,WAAW,CAAC;MACjE,CAAC,CAAC;MAEF,OAAO,IAAI,CAACrF,cAAc,CAAC0F,SAAS,CAAC;MAErC,IAAIrF,MAAM,EAAE;QACV,IAAI,CAACA,MAAM,EAAE;MACf;IACF;EAAC;IAAA;IAAA,OAED,kBAAgB;MACd,OAAO,IAAI,CAACG,YAAY,EAAE;IAC5B;EAAC;IAAA;IAAA,OAED,iBAAe;MACb,IAAI,CAACR,cAAc,GAAG,CAAC,CAAC;MACxB,IAAI,CAACD,eAAe,GAAG,CAAC;MACxB,IAAI,CAACD,cAAc,GAAG,CAAC;IACzB;EAAC;IAAA;IAAA,OAED,8BAA4BC,eAAuB,EAAED,cAAsB,EAAE;MAC3E,IAAI,CAACC,eAAe,GAAGA,eAAe;MACtC,IAAI,CAACD,cAAc,GAAGA,cAAc;MAEpC,IAAI,CAACU,YAAY,EAAE;IACrB;EAAC;EAAA;AAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RemoteMediaGroup","mediaRequestManager","receiveSlots","priority","commitMediaRequest","options","unpinnedRemoteMedia","map","slot","RemoteMedia","resolution","pinnedRemoteMedia","sendActiveSpeakerMediaRequest","filter","remoteMediaCsis","commit","csi","remoteMedia","indexOf","unpinId","splice","push","Error","id","sendMediaRequest","pinId","cancelMediaRequest","cancelActiveSpeakerMediaRequest","targetCsi","LoggerProxy","logger","log","idx","preferLiveVideo","mediaRequestId","addRequest","policyInfo","policy","crossPriorityDuplication","crossPolicyDuplication","namedMediaGroups","namedMediaGroup","value","undefined","getUnderlyingReceiveSlot","codecInfo","codec","maxFs","getMaxFs","cancelRequest","type","forEach","stop","includes"],"sources":["remoteMediaGroup.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable require-jsdoc */\n/* eslint-disable import/prefer-default-export */\nimport {forEach} from 'lodash';\nimport {NamedMediaGroup} from '@webex/json-multistream';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {getMaxFs, RemoteMedia, RemoteVideoResolution} from './remoteMedia';\nimport {MediaRequestId, MediaRequestManager} from './mediaRequestManager';\nimport {CSI, ReceiveSlot} from './receiveSlot';\n\ntype Options = {\n resolution?: RemoteVideoResolution; // applies only to groups of type MediaType.VideoMain and MediaType.VideoSlides\n preferLiveVideo?: boolean; // applies only to groups of type MediaType.VideoMain and MediaType.VideoSlides\n namedMediaGroup?: NamedMediaGroup; // applies only to named media groups for audio\n};\n\nexport class RemoteMediaGroup {\n private mediaRequestManager: MediaRequestManager;\n\n private priority: number;\n\n private options: Options;\n\n private unpinnedRemoteMedia: RemoteMedia[];\n\n private mediaRequestId?: MediaRequestId; // id of the \"active-speaker\" media request id\n\n private pinnedRemoteMedia: RemoteMedia[];\n\n constructor(\n mediaRequestManager: MediaRequestManager,\n receiveSlots: ReceiveSlot[],\n priority: number,\n commitMediaRequest: boolean,\n options: Options = {}\n ) {\n this.mediaRequestManager = mediaRequestManager;\n this.priority = priority;\n this.options = options;\n\n this.unpinnedRemoteMedia = receiveSlots.map(\n (slot) =>\n new RemoteMedia(slot, this.mediaRequestManager, {\n resolution: this.options.resolution,\n })\n );\n this.pinnedRemoteMedia = [];\n\n this.sendActiveSpeakerMediaRequest(commitMediaRequest);\n }\n\n /**\n * Gets the array of remote media elements from the group\n *\n * @param {string} filter - 'all' (default) returns both pinned and unpinned\n * @returns {Array<RemoteMedia>}\n */\n public getRemoteMedia(filter: 'all' | 'pinned' | 'unpinned' = 'all') {\n if (filter === 'unpinned') {\n // return a shallow copy so that the client cannot modify this.unpinnedRemoteMedia array\n return [...this.unpinnedRemoteMedia];\n }\n if (filter === 'pinned') {\n // return a shallow copy so that the client cannot modify this.pinnedRemoteMedia array\n return [...this.pinnedRemoteMedia];\n }\n\n return [...this.unpinnedRemoteMedia, ...this.pinnedRemoteMedia];\n }\n\n /**\n * Sets CSIs for multiple RemoteMedia instances belonging to this RemoteMediaGroup.\n * For each entry in the remoteMediaCsis array:\n * - if csi is specified, the RemoteMedia instance is pinned to that CSI\n * - if csi is undefined, the RemoteMedia instance is unpinned\n * @internal\n */\n public setActiveSpeakerCsis(\n remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: number}[],\n commit = true\n ): void {\n forEach(remoteMediaCsis, ({csi, remoteMedia}) => {\n if (csi) {\n if (!(this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0)) {\n const unpinId = this.unpinnedRemoteMedia.indexOf(remoteMedia);\n if (unpinId >= 0) {\n this.unpinnedRemoteMedia.splice(unpinId, 1);\n this.pinnedRemoteMedia.push(remoteMedia);\n } else {\n throw new Error(\n `failed to pin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n }\n remoteMedia.sendMediaRequest(csi, false);\n } else {\n if (!(this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0)) {\n const pinId = this.pinnedRemoteMedia.indexOf(remoteMedia);\n if (pinId >= 0) {\n this.pinnedRemoteMedia.splice(pinId, 1);\n this.unpinnedRemoteMedia.push(remoteMedia);\n } else {\n throw new Error(\n `failed to unpin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n }\n remoteMedia.cancelMediaRequest(false);\n }\n });\n this.cancelActiveSpeakerMediaRequest(false);\n this.sendActiveSpeakerMediaRequest(false);\n if (commit) {\n this.mediaRequestManager.commit();\n }\n }\n\n /**\n * Pins a specific remote media instance to a specfic CSI, so the media will\n * no longer come from active speaker, but from that CSI.\n * If no CSI is given, the current CSI value is used.\n *\n */\n public pin(remoteMedia: RemoteMedia, csi?: CSI): void {\n // if csi is not specified, use the current one\n const targetCsi = csi || remoteMedia.csi;\n\n if (!targetCsi) {\n throw new Error(\n `failed to pin a remote media object ${remoteMedia.id}, because it has no CSI set and no CSI value was given`\n );\n }\n\n if (this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n if (targetCsi === remoteMedia.csi) {\n // remote media already pinned to target CSI, nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaGroup#pin --> remote media ${remoteMedia.id} already pinned`\n );\n\n return;\n }\n } else {\n const idx = this.unpinnedRemoteMedia.indexOf(remoteMedia);\n\n if (idx < 0) {\n throw new Error(\n `failed to pin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n\n this.unpinnedRemoteMedia.splice(idx, 1);\n this.pinnedRemoteMedia.push(remoteMedia);\n\n this.cancelActiveSpeakerMediaRequest(false);\n this.sendActiveSpeakerMediaRequest(false);\n }\n\n remoteMedia.sendMediaRequest(targetCsi, false);\n this.mediaRequestManager.commit();\n }\n\n /**\n * Unpins a remote media instance, so that it will again provide media from active speakers\n *\n */\n public unpin(remoteMedia: RemoteMedia) {\n if (this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n LoggerProxy.logger.log(\n `RemoteMediaGroup#pin --> remote media ${remoteMedia.id} already unpinned`\n );\n\n return;\n }\n const idx = this.pinnedRemoteMedia.indexOf(remoteMedia);\n\n if (idx < 0) {\n throw new Error(\n `failed to unpin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n\n this.pinnedRemoteMedia.splice(idx, 1);\n this.unpinnedRemoteMedia.push(remoteMedia);\n\n remoteMedia.cancelMediaRequest(false);\n this.cancelActiveSpeakerMediaRequest(false);\n this.sendActiveSpeakerMediaRequest(false);\n this.mediaRequestManager.commit();\n }\n\n public isPinned(remoteMedia: RemoteMedia) {\n if (this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n return false;\n }\n if (this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n return true;\n }\n\n throw new Error(`remote media object ${remoteMedia.id} not found in the group`);\n }\n\n /**\n * setPreferLiveVideo - sets preferLiveVideo to true/false\n * @internal\n */\n public setPreferLiveVideo(preferLiveVideo: boolean, commit: boolean) {\n if (this.options.preferLiveVideo !== preferLiveVideo) {\n this.options.preferLiveVideo = preferLiveVideo;\n this.sendActiveSpeakerMediaRequest(commit);\n }\n }\n\n private sendActiveSpeakerMediaRequest(commit: boolean) {\n this.cancelActiveSpeakerMediaRequest(false);\n\n this.mediaRequestId = this.mediaRequestManager.addRequest(\n {\n policyInfo: {\n policy: 'active-speaker',\n priority: this.priority,\n crossPriorityDuplication: false,\n crossPolicyDuplication: false,\n preferLiveVideo: !!this.options?.preferLiveVideo,\n namedMediaGroups: this.options.namedMediaGroup?.value\n ? [this.options?.namedMediaGroup]\n : undefined,\n },\n receiveSlots: this.unpinnedRemoteMedia.map((remoteMedia) =>\n remoteMedia.getUnderlyingReceiveSlot()\n ) as ReceiveSlot[],\n codecInfo: this.options.resolution && {\n codec: 'h264',\n maxFs: getMaxFs(this.options.resolution),\n },\n },\n commit\n );\n }\n\n private cancelActiveSpeakerMediaRequest(commit: boolean) {\n if (this.mediaRequestId) {\n this.mediaRequestManager.cancelRequest(this.mediaRequestId, commit);\n this.mediaRequestId = undefined;\n }\n }\n\n /**\n * setNamedMediaGroup - sets named media group type and value\n * @internal\n */\n public setNamedMediaGroup(namedMediaGroup: NamedMediaGroup, commit: boolean) {\n if (\n this.options.namedMediaGroup.value !== namedMediaGroup.value ||\n this.options.namedMediaGroup.type !== namedMediaGroup.type\n ) {\n this.options.namedMediaGroup = namedMediaGroup;\n this.sendActiveSpeakerMediaRequest(commit);\n }\n }\n\n /**\n * Invalidates the remote media group by clearing the references to the receive slots\n * used by all remote media from that group and cancelling all media requests.\n * After this call the remote media group is unusable.\n *\n * @param{boolean} commit whether to commit the cancellation of media requests\n * @internal\n */\n public stop(commit = true) {\n this.unpinnedRemoteMedia.forEach((remoteMedia) => remoteMedia.stop(false));\n this.pinnedRemoteMedia.forEach((remoteMedia) => remoteMedia.stop(false));\n this.cancelActiveSpeakerMediaRequest(false);\n\n if (commit) {\n this.mediaRequestManager.commit();\n }\n }\n\n /**\n * Checks if a given RemoteMedia instance belongs to this group.\n *\n * @param remoteMedia RemoteMedia instance to check\n * @param filter controls which remote media from the group to check\n * @returns true if remote media is found\n */\n public includes(\n remoteMedia: RemoteMedia,\n filter: 'all' | 'pinned' | 'unpinned' = 'all'\n ): boolean {\n if (filter === 'pinned') {\n return this.pinnedRemoteMedia.includes(remoteMedia);\n }\n if (filter === 'unpinned') {\n return this.unpinnedRemoteMedia.includes(remoteMedia);\n }\n\n return (\n this.unpinnedRemoteMedia.includes(remoteMedia) || this.pinnedRemoteMedia.includes(remoteMedia)\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["RemoteMediaGroup","mediaRequestManager","receiveSlots","priority","commitMediaRequest","options","unpinnedRemoteMedia","map","slot","RemoteMedia","resolution","pinnedRemoteMedia","sendActiveSpeakerMediaRequest","filter","remoteMediaCsis","commit","csi","remoteMedia","indexOf","unpinId","splice","push","Error","id","sendMediaRequest","pinId","cancelMediaRequest","cancelActiveSpeakerMediaRequest","targetCsi","LoggerProxy","logger","log","idx","preferLiveVideo","mediaRequestId","addRequest","policyInfo","policy","crossPriorityDuplication","crossPolicyDuplication","namedMediaGroups","namedMediaGroup","value","undefined","getUnderlyingReceiveSlot","codecInfo","codec","maxFs","getMaxFs","cancelRequest","type","forEach","stop","includes"],"sources":["remoteMediaGroup.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable require-jsdoc */\n/* eslint-disable import/prefer-default-export */\nimport {forEach} from 'lodash';\nimport {NamedMediaGroup} from '@webex/internal-media-core';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {getMaxFs, RemoteMedia, RemoteVideoResolution} from './remoteMedia';\nimport {MediaRequestId, MediaRequestManager} from './mediaRequestManager';\nimport {CSI, ReceiveSlot} from './receiveSlot';\n\ntype Options = {\n resolution?: RemoteVideoResolution; // applies only to groups of type MediaType.VideoMain and MediaType.VideoSlides\n preferLiveVideo?: boolean; // applies only to groups of type MediaType.VideoMain and MediaType.VideoSlides\n namedMediaGroup?: NamedMediaGroup; // applies only to named media groups for audio\n};\n\nexport class RemoteMediaGroup {\n private mediaRequestManager: MediaRequestManager;\n\n private priority: number;\n\n private options: Options;\n\n private unpinnedRemoteMedia: RemoteMedia[];\n\n private mediaRequestId?: MediaRequestId; // id of the \"active-speaker\" media request id\n\n private pinnedRemoteMedia: RemoteMedia[];\n\n constructor(\n mediaRequestManager: MediaRequestManager,\n receiveSlots: ReceiveSlot[],\n priority: number,\n commitMediaRequest: boolean,\n options: Options = {}\n ) {\n this.mediaRequestManager = mediaRequestManager;\n this.priority = priority;\n this.options = options;\n\n this.unpinnedRemoteMedia = receiveSlots.map(\n (slot) =>\n new RemoteMedia(slot, this.mediaRequestManager, {\n resolution: this.options.resolution,\n })\n );\n this.pinnedRemoteMedia = [];\n\n this.sendActiveSpeakerMediaRequest(commitMediaRequest);\n }\n\n /**\n * Gets the array of remote media elements from the group\n *\n * @param {string} filter - 'all' (default) returns both pinned and unpinned\n * @returns {Array<RemoteMedia>}\n */\n public getRemoteMedia(filter: 'all' | 'pinned' | 'unpinned' = 'all') {\n if (filter === 'unpinned') {\n // return a shallow copy so that the client cannot modify this.unpinnedRemoteMedia array\n return [...this.unpinnedRemoteMedia];\n }\n if (filter === 'pinned') {\n // return a shallow copy so that the client cannot modify this.pinnedRemoteMedia array\n return [...this.pinnedRemoteMedia];\n }\n\n return [...this.unpinnedRemoteMedia, ...this.pinnedRemoteMedia];\n }\n\n /**\n * Sets CSIs for multiple RemoteMedia instances belonging to this RemoteMediaGroup.\n * For each entry in the remoteMediaCsis array:\n * - if csi is specified, the RemoteMedia instance is pinned to that CSI\n * - if csi is undefined, the RemoteMedia instance is unpinned\n * @internal\n */\n public setActiveSpeakerCsis(\n remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: number}[],\n commit = true\n ): void {\n forEach(remoteMediaCsis, ({csi, remoteMedia}) => {\n if (csi) {\n if (!(this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0)) {\n const unpinId = this.unpinnedRemoteMedia.indexOf(remoteMedia);\n if (unpinId >= 0) {\n this.unpinnedRemoteMedia.splice(unpinId, 1);\n this.pinnedRemoteMedia.push(remoteMedia);\n } else {\n throw new Error(\n `failed to pin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n }\n remoteMedia.sendMediaRequest(csi, false);\n } else {\n if (!(this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0)) {\n const pinId = this.pinnedRemoteMedia.indexOf(remoteMedia);\n if (pinId >= 0) {\n this.pinnedRemoteMedia.splice(pinId, 1);\n this.unpinnedRemoteMedia.push(remoteMedia);\n } else {\n throw new Error(\n `failed to unpin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n }\n remoteMedia.cancelMediaRequest(false);\n }\n });\n this.cancelActiveSpeakerMediaRequest(false);\n this.sendActiveSpeakerMediaRequest(false);\n if (commit) {\n this.mediaRequestManager.commit();\n }\n }\n\n /**\n * Pins a specific remote media instance to a specfic CSI, so the media will\n * no longer come from active speaker, but from that CSI.\n * If no CSI is given, the current CSI value is used.\n *\n */\n public pin(remoteMedia: RemoteMedia, csi?: CSI): void {\n // if csi is not specified, use the current one\n const targetCsi = csi || remoteMedia.csi;\n\n if (!targetCsi) {\n throw new Error(\n `failed to pin a remote media object ${remoteMedia.id}, because it has no CSI set and no CSI value was given`\n );\n }\n\n if (this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n if (targetCsi === remoteMedia.csi) {\n // remote media already pinned to target CSI, nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaGroup#pin --> remote media ${remoteMedia.id} already pinned`\n );\n\n return;\n }\n } else {\n const idx = this.unpinnedRemoteMedia.indexOf(remoteMedia);\n\n if (idx < 0) {\n throw new Error(\n `failed to pin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n\n this.unpinnedRemoteMedia.splice(idx, 1);\n this.pinnedRemoteMedia.push(remoteMedia);\n\n this.cancelActiveSpeakerMediaRequest(false);\n this.sendActiveSpeakerMediaRequest(false);\n }\n\n remoteMedia.sendMediaRequest(targetCsi, false);\n this.mediaRequestManager.commit();\n }\n\n /**\n * Unpins a remote media instance, so that it will again provide media from active speakers\n *\n */\n public unpin(remoteMedia: RemoteMedia) {\n if (this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n LoggerProxy.logger.log(\n `RemoteMediaGroup#pin --> remote media ${remoteMedia.id} already unpinned`\n );\n\n return;\n }\n const idx = this.pinnedRemoteMedia.indexOf(remoteMedia);\n\n if (idx < 0) {\n throw new Error(\n `failed to unpin a remote media object ${remoteMedia.id}, because it is not found in this remote media group`\n );\n }\n\n this.pinnedRemoteMedia.splice(idx, 1);\n this.unpinnedRemoteMedia.push(remoteMedia);\n\n remoteMedia.cancelMediaRequest(false);\n this.cancelActiveSpeakerMediaRequest(false);\n this.sendActiveSpeakerMediaRequest(false);\n this.mediaRequestManager.commit();\n }\n\n public isPinned(remoteMedia: RemoteMedia) {\n if (this.unpinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n return false;\n }\n if (this.pinnedRemoteMedia.indexOf(remoteMedia) >= 0) {\n return true;\n }\n\n throw new Error(`remote media object ${remoteMedia.id} not found in the group`);\n }\n\n /**\n * setPreferLiveVideo - sets preferLiveVideo to true/false\n * @internal\n */\n public setPreferLiveVideo(preferLiveVideo: boolean, commit: boolean) {\n if (this.options.preferLiveVideo !== preferLiveVideo) {\n this.options.preferLiveVideo = preferLiveVideo;\n this.sendActiveSpeakerMediaRequest(commit);\n }\n }\n\n private sendActiveSpeakerMediaRequest(commit: boolean) {\n this.cancelActiveSpeakerMediaRequest(false);\n\n this.mediaRequestId = this.mediaRequestManager.addRequest(\n {\n policyInfo: {\n policy: 'active-speaker',\n priority: this.priority,\n crossPriorityDuplication: false,\n crossPolicyDuplication: false,\n preferLiveVideo: !!this.options?.preferLiveVideo,\n namedMediaGroups: this.options.namedMediaGroup?.value\n ? [this.options?.namedMediaGroup]\n : undefined,\n },\n receiveSlots: this.unpinnedRemoteMedia.map((remoteMedia) =>\n remoteMedia.getUnderlyingReceiveSlot()\n ) as ReceiveSlot[],\n codecInfo: this.options.resolution && {\n codec: 'h264',\n maxFs: getMaxFs(this.options.resolution),\n },\n },\n commit\n );\n }\n\n private cancelActiveSpeakerMediaRequest(commit: boolean) {\n if (this.mediaRequestId) {\n this.mediaRequestManager.cancelRequest(this.mediaRequestId, commit);\n this.mediaRequestId = undefined;\n }\n }\n\n /**\n * setNamedMediaGroup - sets named media group type and value\n * @internal\n */\n public setNamedMediaGroup(namedMediaGroup: NamedMediaGroup, commit: boolean) {\n if (\n this.options.namedMediaGroup.value !== namedMediaGroup.value ||\n this.options.namedMediaGroup.type !== namedMediaGroup.type\n ) {\n this.options.namedMediaGroup = namedMediaGroup;\n this.sendActiveSpeakerMediaRequest(commit);\n }\n }\n\n /**\n * Invalidates the remote media group by clearing the references to the receive slots\n * used by all remote media from that group and cancelling all media requests.\n * After this call the remote media group is unusable.\n *\n * @param{boolean} commit whether to commit the cancellation of media requests\n * @internal\n */\n public stop(commit = true) {\n this.unpinnedRemoteMedia.forEach((remoteMedia) => remoteMedia.stop(false));\n this.pinnedRemoteMedia.forEach((remoteMedia) => remoteMedia.stop(false));\n this.cancelActiveSpeakerMediaRequest(false);\n\n if (commit) {\n this.mediaRequestManager.commit();\n }\n }\n\n /**\n * Checks if a given RemoteMedia instance belongs to this group.\n *\n * @param remoteMedia RemoteMedia instance to check\n * @param filter controls which remote media from the group to check\n * @returns true if remote media is found\n */\n public includes(\n remoteMedia: RemoteMedia,\n filter: 'all' | 'pinned' | 'unpinned' = 'all'\n ): boolean {\n if (filter === 'pinned') {\n return this.pinnedRemoteMedia.includes(remoteMedia);\n }\n if (filter === 'unpinned') {\n return this.unpinnedRemoteMedia.includes(remoteMedia);\n }\n\n return (\n this.unpinnedRemoteMedia.includes(remoteMedia) || this.pinnedRemoteMedia.includes(remoteMedia)\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AllEqualLayout","activeSpeakerVideoPaneGroups","id","numPanes","size","priority","SingleLayout","OnePlusFiveLayout","TwoMainPlusSixSmallLayout","RemoteScreenShareWithSmallThumbnailsLayout","screenShareVideo","Stage2x2With6ThumbnailsLayout","memberVideoPanes","csi","undefined","DefaultConfiguration","audio","numOfActiveSpeakerStreams","numOfScreenShareStreams","video","preferLiveVideo","initialLayoutId","layouts","AllEqual","OnePlusFive","Single","Stage","ScreenShareView","Event","RemoteMediaManager","receiveSlotManager","mediaRequestManagers","config","started","media","main","si","activeSpeakerGroups","memberPanes","screenShare","checkConfigValidity","slots","unused","activeSpeaker","receiverSelected","receiveSlotAllocations","LoggerProxy","logger","log","Error","forEach","layout","groupIds","paneIds","groupPriorites","group","pane","createAudioMedia","createScreenShareReceiveSlots","createScreenShareAudioMedia","preallocateVideoReceiveSlots","setLayout","invalidateCurrentRemoteMedia","screenShareAudio","commit","slot","releaseSlot","length","push","releaseUnusedVideoSlots","currentLayout","currentLayoutId","activeSpeakerCount","reduce","sum","paneGroup","receiverSelectedCount","maxNumVideoPanesRequired","maxValue","Math","max","getRequiredNumVideoSlotsForLayout","allocateSlot","MediaType","VideoMain","layoutId","updateVideoReceiveSlots","updateVideoRemoteMediaObjects","updateScreenShareVideoRemoteMediaObject","emitVideoLayoutChangedEvent","activeSpeakerGroup","setPreferLiveVideo","remoteMediaCsis","remoteMediaGroup","groupRemoteMediaCsis","filter","remoteMedia","includes","setActiveSpeakerCsis","mediaType","languageId","AudioMain","value","namedMediaGroup","type","NAMED_MEDIA_GROUP_TYPE_AUDIO","createInterpretationAudioMedia","setNamedMediaGroup","i","RemoteMediaGroup","emit","file","function","AudioCreated","commitRequest","InterpretationAudioCreated","AudioSlides","isAnyLayoutContainingScreenShareVideo","some","VideoSlides","ScreenShareAudioCreated","requiredCsis","memberVideoPane","isCsiNeededByCurrentLayout","notNeededReceiverSelectedSlots","sort","a","b","paneIndex","freeSlot","shift","memberPane","existingSlot","find","isExistingSlotAlreadyAllocated","pop","requiredNumSlots","totalNumSlots","numSlotsToCreate","logMessage","groupName","map","logString","join","key","logMainVideoReceiveSlots","logMainAudioReceiveSlots","logSlidesVideoReceiveSlots","logSlidesAudioReceiveSlots","trimActiveSpeakerSlots","trimReceiverSelectedSlots","refillRequiredSlotsIfNeeded","allocateSlotsToActiveSpeakerPaneGroups","allocateSlotsToReceiverSelectedVideoPaneGroups","groupId","paneGroupInCurrentLayout","groupInLayout","mediaGroup","resolution","warn","paneId","paneInCurrentLayout","paneInLayout","RemoteMedia","sendMediaRequest","options","stop","VideoLayoutChanged","activeSpeakerVideoPanes","getRemoteMedia","cancelMediaRequest","newPane","receiveSlot","reject","resolve","getUnderlyingReceiveSlot","index","indexOf","splice","pin","unpin","isPinned","EventsScope"],"sources":["remoteMediaManager.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\nimport {cloneDeep, forEach, remove} from 'lodash';\nimport {EventMap} from 'typed-emitter';\nimport {MediaType} from '@webex/internal-media-core';\nimport {NamedMediaGroup} from '@webex/json-multistream';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nimport {RemoteMedia, RemoteVideoResolution} from './remoteMedia';\nimport {ReceiveSlot, CSI} from './receiveSlot';\nimport {ReceiveSlotManager} from './receiveSlotManager';\nimport {RemoteMediaGroup} from './remoteMediaGroup';\nimport {MediaRequestManager} from './mediaRequestManager';\nimport {NAMED_MEDIA_GROUP_TYPE_AUDIO} from '../constants';\n\nexport type PaneSize = RemoteVideoResolution;\nexport type LayoutId = string;\nexport type PaneId = string;\nexport type PaneGroupId = string;\n\nexport interface ActiveSpeakerVideoPaneGroup {\n id: PaneGroupId;\n numPanes: number; // maximum number of panes in the group (actual number may be lower, if there are not enough participants in the meeting)\n size: PaneSize; // preferred size for all panes in the group\n priority: number; // 0-255 (255 = highest priority), each group must have a different priority from all other groups\n}\n\nexport interface MemberVideoPane {\n id: PaneId;\n size: PaneSize;\n csi?: CSI;\n}\n\nexport interface VideoLayout {\n screenShareVideo?: {\n size: PaneSize;\n };\n activeSpeakerVideoPaneGroups?: ActiveSpeakerVideoPaneGroup[]; // list of active speaker video pane groups\n memberVideoPanes?: MemberVideoPane[]; // list of video panes for specific members, CSI values can be changed later via setVideoPaneCsi()\n}\n\nexport interface Configuration {\n audio: {\n numOfActiveSpeakerStreams: number; // number of audio streams we want to receive\n numOfScreenShareStreams: number; // 1 should be enough, because in webex only 1 person at a time can be presenting screen share\n };\n video: {\n preferLiveVideo: boolean; // applies to all pane groups with active speaker policy\n initialLayoutId: LayoutId;\n\n layouts: {[key: LayoutId]: VideoLayout}; // a map of all available layouts, a layout can be set via setLayout() method\n };\n namedMediaGroup?: NamedMediaGroup;\n}\n\n/* Predefined layouts: */\n\n// An \"all equal\" grid, with size up to 3 x 3 = 9:\nconst AllEqualLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 9,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with just a single remote active speaker video pane:\nconst SingleLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 1,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with 1 big pane for the highest priority active speaker and 5 small panes for other active speakers:\nconst OnePlusFiveLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainBigOne',\n numPanes: 1,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondarySetOfSmallPanes',\n numPanes: 5,\n size: 'very small',\n priority: 254,\n },\n ],\n};\n\n// A layout with 2 big panes for 2 main active speakers and a strip of 6 small panes for other active speakers:\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst TwoMainPlusSixSmallLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainGroupWith2BigPanes',\n numPanes: 2,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondaryGroupOfSmallPanes',\n numPanes: 6,\n size: 'small',\n priority: 254,\n },\n ],\n};\n\n// A strip of 8 small video panes (thumbnails) displayed at the top of a remote screenshare:\nconst RemoteScreenShareWithSmallThumbnailsLayout: VideoLayout = {\n screenShareVideo: {size: 'best'},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 8,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n};\n\n// A staged layout with 4 pre-selected meeting participants in the main 2x2 grid and 6 small panes for other active speakers at the top:\nconst Stage2x2With6ThumbnailsLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 6,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n memberVideoPanes: [\n {id: 'stage-1', size: 'medium', csi: undefined},\n {id: 'stage-2', size: 'medium', csi: undefined},\n {id: 'stage-3', size: 'medium', csi: undefined},\n {id: 'stage-4', size: 'medium', csi: undefined},\n ],\n};\n\n/**\n * Default configuration:\n * - uses 3 audio streams\n * - prefers active speakers with live video (e.g. are not audio only or video muted) over active speakers without live video\n * - has a few layouts defined, including 1 that contains remote screen share (ScreenShareView)\n */\nexport const DefaultConfiguration: Configuration = {\n audio: {\n numOfActiveSpeakerStreams: 3,\n numOfScreenShareStreams: 1,\n },\n video: {\n preferLiveVideo: true,\n initialLayoutId: 'AllEqual',\n\n layouts: {\n AllEqual: AllEqualLayout,\n OnePlusFive: OnePlusFiveLayout,\n Single: SingleLayout,\n Stage: Stage2x2With6ThumbnailsLayout,\n ScreenShareView: RemoteScreenShareWithSmallThumbnailsLayout,\n },\n },\n};\n\nexport enum Event {\n // events for audio streams\n AudioCreated = 'AudioCreated',\n InterpretationAudioCreated = 'InterpretationAudioCreated',\n ScreenShareAudioCreated = 'ScreenShareAudioCreated',\n\n // events for video streams\n VideoLayoutChanged = 'VideoLayoutChanged',\n}\n\nexport interface VideoLayoutChangedEventData {\n layoutId: LayoutId;\n activeSpeakerVideoPanes: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberVideoPanes: {[key: PaneId]: RemoteMedia};\n screenShareVideo?: RemoteMedia;\n}\nexport interface Events extends EventMap {\n // audio\n [Event.AudioCreated]: (audio: RemoteMediaGroup) => void;\n [Event.ScreenShareAudioCreated]: (screenShareAudio: RemoteMediaGroup) => void;\n\n // video\n [Event.VideoLayoutChanged]: (data: VideoLayoutChangedEventData) => void;\n}\n\n/**\n * A helper class that manages all remote audio/video streams in order to achieve a predefined set of layouts.\n * It also creates a fixed number of audio streams and these don't change during the meeting.\n *\n * Things that RemoteMediaManager does:\n * - owns the receive slots (creates them when needed, and re-uses them when switching layouts)\n * - constructs appropriate RemoteMedia and RemoteMediaGroup objects and sends appropriate mediaRequests\n */\nexport class RemoteMediaManager extends EventsScope {\n private config: Configuration;\n\n private started: boolean;\n\n private receiveSlotManager: ReceiveSlotManager;\n\n private mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n screenShareAudio: MediaRequestManager;\n screenShareVideo: MediaRequestManager;\n };\n\n private currentLayout?: VideoLayout;\n\n private slots: {\n audio: {\n main: ReceiveSlot[];\n si: ReceiveSlot;\n };\n screenShare: {\n audio: ReceiveSlot[];\n video?: ReceiveSlot;\n };\n video: {\n unused: ReceiveSlot[];\n activeSpeaker: ReceiveSlot[];\n receiverSelected: ReceiveSlot[];\n };\n };\n\n private media: {\n audio: {\n main?: RemoteMediaGroup;\n si?: RemoteMediaGroup;\n };\n video: {\n activeSpeakerGroups: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberPanes: {[key: PaneId]: RemoteMedia};\n };\n screenShare: {\n audio?: RemoteMediaGroup;\n video?: RemoteMediaGroup;\n };\n };\n\n private receiveSlotAllocations: {\n activeSpeaker: {[key: PaneGroupId]: {slots: ReceiveSlot[]}};\n receiverSelected: {[key: PaneId]: ReceiveSlot};\n };\n\n private currentLayoutId?: LayoutId;\n\n /**\n * Constructor\n *\n * @param {ReceiveSlotManager} receiveSlotManager\n * @param {{audio: MediaRequestManager, video: mediaRequestManagers}} mediaRequestManagers\n * @param {Configuration} config Configuration describing what video layouts to use during the meeting\n */\n constructor(\n receiveSlotManager: ReceiveSlotManager,\n mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n screenShareAudio: MediaRequestManager;\n screenShareVideo: MediaRequestManager;\n },\n config: Configuration = DefaultConfiguration\n ) {\n super();\n this.started = false;\n this.config = config;\n this.receiveSlotManager = receiveSlotManager;\n this.mediaRequestManagers = mediaRequestManagers;\n this.media = {\n audio: {\n main: undefined,\n si: undefined,\n },\n video: {\n activeSpeakerGroups: {},\n memberPanes: {},\n },\n screenShare: {\n audio: undefined,\n video: undefined,\n },\n };\n\n this.checkConfigValidity();\n\n this.slots = {\n audio: {\n main: [],\n si: undefined,\n },\n screenShare: {\n audio: [],\n video: undefined,\n },\n video: {\n unused: [],\n activeSpeaker: [],\n receiverSelected: [],\n },\n };\n\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#constructor --> RemoteMediaManager created with config: ${JSON.stringify(\n this.config\n )}`\n );\n }\n\n /**\n * Checks if configuration is valid, throws an error if it's not\n */\n private checkConfigValidity() {\n if (!(this.config.video.initialLayoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid config: initialLayoutId \"${this.config.video.initialLayoutId}\" doesn't match any of the layouts`\n );\n }\n\n // check if each layout is valid\n Object.values(this.config.video.layouts).forEach((layout) => {\n const groupIds = {};\n const paneIds = {};\n const groupPriorites = {};\n\n layout.activeSpeakerVideoPaneGroups?.forEach((group) => {\n if (groupIds[group.id]) {\n throw new Error(\n `invalid config: duplicate active speaker video pane group id: ${group.id}`\n );\n }\n groupIds[group.id] = true;\n\n if (groupPriorites[group.priority]) {\n throw new Error(\n `invalid config: multiple active speaker video pane groups have same priority: ${group.priority}`\n );\n }\n groupPriorites[group.priority] = true;\n });\n\n layout.memberVideoPanes?.forEach((pane) => {\n if (paneIds[pane.id]) {\n throw new Error(`invalid config: duplicate member video pane id: ${pane.id}`);\n }\n paneIds[pane.id] = true;\n });\n });\n }\n\n /**\n * Starts the RemoteMediaManager.\n *\n * @returns {Promise}\n */\n public async start() {\n if (this.started) {\n throw new Error('start() failure: already started');\n }\n this.started = true;\n\n await this.createAudioMedia();\n\n await this.createScreenShareReceiveSlots();\n this.createScreenShareAudioMedia();\n\n await this.preallocateVideoReceiveSlots();\n\n await this.setLayout(this.config.video.initialLayoutId);\n }\n\n /**\n * Releases all the used resources (like allocated receive slots). This function needs\n * to be called when we leave the meeting, etc.\n */\n public stop() {\n // invalidate all remoteMedia objects\n this.invalidateCurrentRemoteMedia({\n audio: true,\n video: true,\n screenShareAudio: true,\n screenShareVideo: true,\n commit: true,\n });\n\n // release all audio receive slots\n this.slots.audio.main.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.audio.main.length = 0;\n if (this.slots.audio.si) {\n this.receiveSlotManager.releaseSlot(this.slots.audio.si);\n }\n\n // release screen share slots\n this.slots.screenShare.audio.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.screenShare.audio.length = 0;\n if (this.slots.screenShare.video) {\n this.receiveSlotManager.releaseSlot(this.slots.screenShare.video);\n this.slots.screenShare.video = undefined;\n }\n\n // release video slots\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n\n this.slots.video.unused.push(...this.slots.video.receiverSelected);\n this.slots.video.receiverSelected.length = 0;\n\n this.releaseUnusedVideoSlots();\n\n this.currentLayout = undefined;\n this.currentLayoutId = undefined;\n this.started = false;\n }\n\n /**\n * Returns the total number of main video panes required for a given layout\n *\n * @param {VideoLayout} layout\n * @returns {number}\n */\n private getRequiredNumVideoSlotsForLayout(layout?: VideoLayout) {\n if (!layout) {\n return 0;\n }\n\n const activeSpeakerCount =\n layout.activeSpeakerVideoPaneGroups?.reduce(\n (sum, paneGroup) => sum + paneGroup.numPanes,\n 0\n ) || 0;\n\n const receiverSelectedCount = layout.memberVideoPanes?.length || 0;\n\n return activeSpeakerCount + receiverSelectedCount;\n }\n\n /**\n * Allocates the maximum number of panes that any of the configured layouts will require.\n * We do this at the beginning, because it's more efficient (much faster) then allocating receive slots\n * later, after the SDP exchange was done.\n */\n private async preallocateVideoReceiveSlots() {\n const maxNumVideoPanesRequired = Object.values(this.config.video.layouts).reduce(\n (maxValue, layout) => Math.max(maxValue, this.getRequiredNumVideoSlotsForLayout(layout)),\n 0\n );\n\n while (this.slots.video.unused.length < maxNumVideoPanesRequired) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n // eslint-disable-next-line no-await-in-loop\n await this.receiveSlotManager.allocateSlot(MediaType.VideoMain)\n );\n }\n }\n\n /**\n * Changes the layout (triggers Event.VideoLayoutChanged)\n *\n * @param {LayoutId} layoutId new layout id\n * @returns {Promise}\n */\n public async setLayout(layoutId: LayoutId) {\n if (!(layoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid layoutId: \"${layoutId}\" doesn't match any of the configured layouts`\n );\n }\n if (!this.started) {\n throw new Error('setLayout() called before start()');\n }\n LoggerProxy.logger.log(`RemoteMediaManager#setLayout --> new layout selected: ${layoutId}`);\n\n this.currentLayoutId = layoutId;\n this.currentLayout = cloneDeep(this.config.video.layouts[this.currentLayoutId]);\n\n await this.updateVideoReceiveSlots();\n this.updateVideoRemoteMediaObjects();\n this.updateScreenShareVideoRemoteMediaObject();\n this.emitVideoLayoutChangedEvent();\n }\n\n /**\n * Returns the currently selected layout id\n *\n * @returns {LayoutId}\n */\n public getLayoutId(): LayoutId | undefined {\n return this.currentLayoutId;\n }\n\n /**\n * sets the preferLiveVideo\n */\n public setPreferLiveVideo(preferLiveVideo: boolean) {\n LoggerProxy.logger.log(\n `RemoteMediaManager#setPreferLiveVideo --> setPreferLiveVideo is called to set preferLiveVideo to ${preferLiveVideo}`\n );\n this.config.video.preferLiveVideo = preferLiveVideo;\n Object.values(this.media.video.activeSpeakerGroups).forEach((activeSpeakerGroup) => {\n activeSpeakerGroup.setPreferLiveVideo(preferLiveVideo, false);\n });\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Sets CSIs for multiple RemoteMedia instances belonging to RemoteMediaGroup.\n * For each entry in the remoteMediaCsis array:\n * - if csi is specified, the RemoteMedia instance is pinned to that CSI\n * - if csi is undefined, the RemoteMedia instance is unpinned\n */\n public setActiveSpeakerCsis(remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: number}[]) {\n Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {\n const groupRemoteMediaCsis = remoteMediaCsis.filter(({remoteMedia}) =>\n remoteMediaGroup.includes(remoteMedia)\n );\n if (groupRemoteMediaCsis.length > 0) {\n remoteMediaGroup.setActiveSpeakerCsis(groupRemoteMediaCsis, false);\n }\n });\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Sets which named media group need receiving\n * @param {MediaType} mediaType of the stream\n * @param {number} languageCode of the stream. If the languageId is 0, the named media group request will be canceled,\n * and only receive the main audio stream.\n * @returns {void}\n */\n public async setReceiveNamedMediaGroup(mediaType: MediaType, languageId: number) {\n if (mediaType !== MediaType.AudioMain) {\n throw new Error(`cannot set receive named media group which media type is ${mediaType}`);\n }\n\n const value = languageId;\n if (value === this.config.namedMediaGroup?.value) {\n return;\n }\n\n this.config.namedMediaGroup = {\n type: NAMED_MEDIA_GROUP_TYPE_AUDIO,\n value,\n };\n\n if (!this.media.audio.si) {\n await this.createInterpretationAudioMedia(true);\n } else {\n this.media.audio.si.setNamedMediaGroup(this.config.namedMediaGroup, true);\n }\n }\n\n /**\n * Creates the audio slots\n */\n private async createAudioMedia() {\n // create si audio request\n await this.createInterpretationAudioMedia(false);\n\n // create main audio receive slots\n for (let i = 0; i < this.config.audio.numOfActiveSpeakerStreams; i += 1) {\n // eslint-disable-next-line no-await-in-loop\n const slot = await this.receiveSlotManager.allocateSlot(MediaType.AudioMain);\n\n this.slots.audio.main.push(slot);\n }\n\n // create a remote media group for main audio\n this.media.audio.main = new RemoteMediaGroup(\n this.mediaRequestManagers.audio,\n this.slots.audio.main,\n 255,\n true\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createAudioMedia'},\n Event.AudioCreated,\n this.media.audio.main\n );\n }\n\n /**\n * Creates the audio slots for named media\n */\n private async createInterpretationAudioMedia(commitRequest: boolean) {\n // create slot for interpretation language audio\n if (\n this.config.namedMediaGroup?.type === NAMED_MEDIA_GROUP_TYPE_AUDIO &&\n this.config.namedMediaGroup?.value\n ) {\n this.slots.audio.si = await this.receiveSlotManager.allocateSlot(MediaType.AudioMain);\n\n // create a remote media group for si audio\n this.media.audio.si = new RemoteMediaGroup(\n this.mediaRequestManagers.audio,\n [this.slots.audio.si],\n 255,\n commitRequest,\n {\n namedMediaGroup: this.config.namedMediaGroup,\n }\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createInterpretationAudioMedia'},\n Event.InterpretationAudioCreated,\n this.media.audio.si\n );\n }\n }\n\n /**\n * Creates receive slots required for receiving screen share audio and video\n */\n private async createScreenShareReceiveSlots() {\n // audio\n for (let i = 0; i < this.config.audio.numOfScreenShareStreams; i += 1) {\n // eslint-disable-next-line no-await-in-loop\n const slot = await this.receiveSlotManager.allocateSlot(MediaType.AudioSlides);\n\n this.slots.screenShare.audio.push(slot);\n }\n\n // video\n const isAnyLayoutContainingScreenShareVideo = Object.values(this.config.video.layouts).some(\n (layout) => !!layout.screenShareVideo\n );\n\n if (isAnyLayoutContainingScreenShareVideo) {\n this.slots.screenShare.video = await this.receiveSlotManager.allocateSlot(\n MediaType.VideoSlides\n );\n }\n }\n\n /**\n * Creates RemoteMedia objects for screen share\n */\n private createScreenShareAudioMedia() {\n if (this.slots.screenShare.audio.length > 0) {\n this.media.screenShare.audio = new RemoteMediaGroup(\n this.mediaRequestManagers.screenShareAudio,\n this.slots.screenShare.audio,\n 255,\n true\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createScreenShareAudioMedia'},\n Event.ScreenShareAudioCreated,\n this.media.screenShare.audio\n );\n }\n }\n\n /**\n * Goes over all receiver-selected slots and keeps only the ones that are required by a given layout,\n * the rest are all moved to the \"unused\" list\n */\n private trimReceiverSelectedSlots() {\n const requiredCsis = {};\n\n // fill requiredCsis with all the CSIs that the given layout requires\n this.currentLayout?.memberVideoPanes?.forEach((memberVideoPane) => {\n if (memberVideoPane.csi !== undefined) {\n requiredCsis[memberVideoPane.csi] = true;\n }\n });\n\n const isCsiNeededByCurrentLayout = (csi?: CSI): boolean => {\n if (csi === undefined) {\n return false;\n }\n\n return !!requiredCsis[csi];\n };\n\n // keep receiverSelected slots that match our new requiredCsis, move the rest of receiverSelected slots to unused\n const notNeededReceiverSelectedSlots = remove(\n this.slots.video.receiverSelected,\n (slot) => isCsiNeededByCurrentLayout(slot.csi) === false\n );\n\n this.slots.video.unused.push(...notNeededReceiverSelectedSlots);\n }\n\n /**\n * Releases all the \"unused\" video slots.\n */\n private releaseUnusedVideoSlots() {\n this.slots.video.unused.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.video.unused.length = 0;\n }\n\n /**\n * Allocates receive slots to all active speaker video panes\n * in the current selected layout.\n *\n * Allocation tries to keep the same order of the slots between the previous\n * layout and the new one. Sorting helps making sure that highest priority slots\n * go in the same order in the new layout.\n */\n private allocateSlotsToActiveSpeakerPaneGroups() {\n this.currentLayout?.activeSpeakerVideoPaneGroups\n // sorting in descending order based on group priority\n ?.sort((a, b) => (a.priority < b.priority ? 1 : -1))\n ?.forEach((group) => {\n this.receiveSlotAllocations.activeSpeaker[group.id] = {slots: []};\n\n for (let paneIndex = 0; paneIndex < group.numPanes; paneIndex += 1) {\n // allocate a slot from the \"unused\" list, by grabbing in same order (shift) as previous layout\n const freeSlot = this.slots.video.unused.shift();\n\n if (freeSlot) {\n this.slots.video.activeSpeaker.push(freeSlot);\n this.receiveSlotAllocations.activeSpeaker[group.id].slots.push(freeSlot);\n }\n }\n });\n }\n\n /**\n * Allocates receive slots to all receiver selected video panes\n * in the current selected layout\n */\n private allocateSlotsToReceiverSelectedVideoPaneGroups() {\n this.currentLayout?.memberVideoPanes?.forEach((memberPane) => {\n // check if there is existing slot for this csi\n const existingSlot = this.slots.video.receiverSelected.find(\n (slot) => slot.csi === memberPane.csi\n );\n\n const isExistingSlotAlreadyAllocated = Object.values(\n this.receiveSlotAllocations.receiverSelected\n ).includes(existingSlot);\n\n if (memberPane.csi !== undefined && existingSlot && !isExistingSlotAlreadyAllocated) {\n // found it, so use it\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = existingSlot;\n } else {\n // allocate a slot from the \"unused\" list\n const freeSlot = this.slots.video.unused.pop();\n\n if (freeSlot) {\n this.slots.video.receiverSelected.push(freeSlot);\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = freeSlot;\n }\n }\n });\n }\n\n /**\n * Ensures that we have enough slots for the current layout.\n */\n private async refillRequiredSlotsIfNeeded() {\n const requiredNumSlots = this.getRequiredNumVideoSlotsForLayout(this.currentLayout);\n const totalNumSlots =\n this.slots.video.unused.length +\n this.slots.video.activeSpeaker.length +\n this.slots.video.receiverSelected.length;\n\n if (totalNumSlots < requiredNumSlots) {\n let numSlotsToCreate = requiredNumSlots - totalNumSlots;\n\n while (numSlotsToCreate > 0) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n // eslint-disable-next-line no-await-in-loop\n await this.receiveSlotManager.allocateSlot(MediaType.VideoMain)\n );\n numSlotsToCreate -= 1;\n }\n }\n }\n\n /**\n * Move all active speaker slots to \"unused\"\n */\n private trimActiveSpeakerSlots() {\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n }\n\n /**\n * Logs the state of the receive slots\n */\n private logMainVideoReceiveSlots() {\n let logMessage = '';\n forEach(this.receiveSlotAllocations.activeSpeaker, (group, groupName) => {\n logMessage += `\\ngroup: ${groupName}\\n${group.slots\n .map((slot) => slot.logString)\n .join(', ')}`;\n });\n\n logMessage += '\\nreceiverSelected:\\n';\n forEach(this.receiveSlotAllocations.receiverSelected, (slot, key) => {\n logMessage += ` ${key}: ${slot.logString}\\n`;\n });\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#logMainVideoReceiveSlots --> MAIN VIDEO receive slots: unused=${this.slots.video.unused.length}, activeSpeaker=${this.slots.video.activeSpeaker.length}, receiverSelected=${this.slots.video.receiverSelected.length}${logMessage}`\n );\n }\n\n /** logs main audio slots */\n private logMainAudioReceiveSlots() {\n LoggerProxy.logger.log(\n `RemoteMediaManager#logMainAudioReceiveSlots --> MAIN AUDIO receive slots: ${this.slots.audio.main\n .map((slot) => slot.logString)\n .join(', ')}`\n );\n }\n\n /** logs slides video slots */\n private logSlidesVideoReceiveSlots() {\n LoggerProxy.logger.log(\n `RemoteMediaManager#logSlidesVideoReceiveSlots --> SLIDES VIDEO receive slot: ${this.slots.screenShare.video?.logString}`\n );\n }\n\n /** logs slides audio slots */\n private logSlidesAudioReceiveSlots() {\n LoggerProxy.logger.log(\n `RemoteMediaManager#logSlidesAudioReceiveSlots --> SLIDES AUDIO receive slots: ${this.slots.screenShare.audio\n .map((slot) => slot.logString)\n .join(', ')}`\n );\n }\n\n /** Logs all current receive slots */\n public logAllReceiveSlots() {\n this.logMainVideoReceiveSlots();\n this.logMainAudioReceiveSlots();\n this.logSlidesVideoReceiveSlots();\n this.logSlidesAudioReceiveSlots();\n }\n\n /**\n * Makes sure we have the right number of receive slots created for the current layout\n * and allocates them to the right video panes / pane groups\n *\n * @returns {Promise}\n */\n private async updateVideoReceiveSlots() {\n // move all active speaker slots to \"unused\"\n this.trimActiveSpeakerSlots();\n\n // move all no longer needed receiver-selected slots to \"unused\"\n this.trimReceiverSelectedSlots();\n\n // ensure we have enough total slots for current layout\n await this.refillRequiredSlotsIfNeeded();\n\n // allocate the slots to the right panes / pane groups\n // reset allocations\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n // allocate active speaker\n this.allocateSlotsToActiveSpeakerPaneGroups();\n // allocate receiver selected\n this.allocateSlotsToReceiverSelectedVideoPaneGroups();\n\n this.logMainVideoReceiveSlots();\n\n // If this is the initial layout, there may be some \"unused\" slots left because of the preallocation\n // done in this.preallocateVideoReceiveSlots(), so release them now\n this.releaseUnusedVideoSlots();\n }\n\n /**\n * Creates new RemoteMedia and RemoteMediaGroup objects for the current layout\n * and sends the media requests for all of them.\n */\n private updateVideoRemoteMediaObjects() {\n // invalidate all the previous remote media objects and cancel their media requests\n this.invalidateCurrentRemoteMedia({\n audio: false,\n video: true,\n screenShareAudio: false,\n screenShareVideo: false,\n commit: false,\n });\n\n // create new remoteMediaGroup objects\n this.media.video.activeSpeakerGroups = {};\n this.media.video.memberPanes = {};\n\n for (const [groupId, group] of Object.entries(this.receiveSlotAllocations.activeSpeaker)) {\n const paneGroupInCurrentLayout = this.currentLayout?.activeSpeakerVideoPaneGroups?.find(\n (groupInLayout) => groupInLayout.id === groupId\n );\n\n if (paneGroupInCurrentLayout) {\n const mediaGroup = new RemoteMediaGroup(\n this.mediaRequestManagers.video,\n group.slots,\n paneGroupInCurrentLayout.priority,\n false,\n {\n preferLiveVideo: this.config.video.preferLiveVideo,\n resolution: paneGroupInCurrentLayout.size,\n }\n );\n\n this.media.video.activeSpeakerGroups[groupId] = mediaGroup;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a group id ${groupId} from this.receiveSlotAllocations.activeSpeaker cannot be found in the current layout configuration`\n );\n }\n }\n\n // create new remoteMedia objects\n for (const [paneId, slot] of Object.entries(this.receiveSlotAllocations.receiverSelected)) {\n const paneInCurrentLayout = this.currentLayout?.memberVideoPanes?.find(\n (paneInLayout) => paneInLayout.id === paneId\n );\n\n if (paneInCurrentLayout) {\n const remoteMedia = new RemoteMedia(slot, this.mediaRequestManagers.video, {\n resolution: paneInCurrentLayout.size,\n });\n\n if (paneInCurrentLayout.csi) {\n remoteMedia.sendMediaRequest(paneInCurrentLayout.csi, false);\n }\n\n this.media.video.memberPanes[paneId] = remoteMedia;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a pane id ${paneId} from this.receiveSlotAllocations.receiverSelected cannot be found in the current layout configuration`\n );\n }\n }\n\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Checks if current layout requires a screen share.\n * If it does, it creates new RemoteMediaGroup object for screen share\n * and sends the media requests for it.\n * If it doesn't, it makes sure we clean up any RemoteMediaGroup objects\n * created earlier for screen share (for previous layout).\n */\n private updateScreenShareVideoRemoteMediaObject() {\n this.invalidateCurrentRemoteMedia({\n audio: false,\n video: false,\n screenShareAudio: false,\n screenShareVideo: true,\n commit: false,\n });\n\n this.media.screenShare.video = undefined;\n\n if (this.currentLayout?.screenShareVideo) {\n // we create a group of 1, because for screen share we need to use the \"active speaker\" policy\n this.media.screenShare.video = new RemoteMediaGroup(\n this.mediaRequestManagers.screenShareVideo,\n [this.slots.screenShare.video],\n 255,\n false,\n {resolution: this.currentLayout.screenShareVideo.size}\n );\n }\n\n this.mediaRequestManagers.screenShareVideo.commit();\n }\n\n /**\n * Invalidates all remote media objects belonging to currently selected layout\n */\n private invalidateCurrentRemoteMedia(options: {\n audio: boolean;\n video: boolean;\n screenShareAudio: boolean;\n screenShareVideo: boolean;\n commit: boolean;\n }) {\n const {audio, video, screenShareAudio, screenShareVideo, commit} = options;\n\n if (audio) {\n if (this.media.audio.main) {\n this.media.audio.main.stop(commit);\n }\n if (this.media.audio.si) {\n this.media.audio.si.stop(commit);\n }\n }\n if (video) {\n Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {\n remoteMediaGroup.stop(false);\n });\n Object.values(this.media.video.memberPanes).forEach((remoteMedia) => {\n remoteMedia.stop(false);\n });\n if (commit) {\n this.mediaRequestManagers.video.commit();\n }\n }\n\n if (screenShareAudio && this.media.screenShare.audio) {\n this.media.screenShare.audio.stop(commit);\n }\n if (screenShareVideo && this.media.screenShare.video) {\n this.media.screenShare.video.stop(commit);\n }\n }\n\n /** emits Event.VideoLayoutChanged */\n private emitVideoLayoutChangedEvent() {\n // todo: at this point the receive slots might still be showing a participant from previous layout, we should\n // wait for our media requests to be fulfilled, but there is no API for that right now (we could wait for source updates\n // but in some cases they might never come, or would need to always make sure to use a new set of receiver slots)\n // for now it's fine to have it like this, we will re-evaluate if it needs improving after more testing\n\n this.emit(\n {\n file: 'multistream/remoteMediaManager',\n function: 'emitVideoLayoutChangedEvent',\n },\n Event.VideoLayoutChanged,\n {\n layoutId: this.currentLayoutId,\n activeSpeakerVideoPanes: this.media.video.activeSpeakerGroups,\n memberVideoPanes: this.media.video.memberPanes,\n screenShareVideo: this.media.screenShare.video?.getRemoteMedia()[0],\n }\n );\n }\n\n /**\n * Sets a new CSI on a given remote media object\n *\n * @param {RemoteMedia} remoteMedia remote Media object to modify\n * @param {CSI} csi new CSI value, can be null if we want to stop receiving media\n */\n public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi: CSI | null) {\n if (!Object.values(this.media.video.memberPanes).includes(remoteMedia)) {\n throw new Error('remoteMedia not found');\n }\n\n if (csi) {\n remoteMedia.sendMediaRequest(csi, true);\n } else {\n remoteMedia.cancelMediaRequest(true);\n }\n }\n\n /**\n * Adds a new member video pane to the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {MemberVideoPane} newPane\n * @returns {Promise<RemoteMedia>}\n */\n public async addMemberVideoPane(newPane: MemberVideoPane): Promise<RemoteMedia> {\n if (!this.currentLayout) {\n throw new Error('There is no current layout selected, call start() first');\n }\n\n if (!this.currentLayout?.memberVideoPanes) {\n this.currentLayout.memberVideoPanes = [];\n }\n\n if (newPane.id in this.currentLayout.memberVideoPanes) {\n throw new Error(\n `duplicate pane id ${newPane.id} - this pane already exists in current layout's memberVideoPanes`\n );\n }\n\n this.currentLayout.memberVideoPanes.push(newPane);\n\n const receiveSlot = await this.receiveSlotManager.allocateSlot(MediaType.VideoMain);\n\n this.slots.video.receiverSelected.push(receiveSlot);\n\n const remoteMedia = new RemoteMedia(receiveSlot, this.mediaRequestManagers.video, {\n resolution: newPane.size,\n });\n\n if (newPane.csi) {\n remoteMedia.sendMediaRequest(newPane.csi, true);\n }\n\n this.media.video.memberPanes[newPane.id] = remoteMedia;\n\n return remoteMedia;\n }\n\n /**\n * Removes a member video pane from the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {PaneId} paneId pane id of the pane to remove\n * @returns {Promise<void>}\n */\n public removeMemberVideoPane(paneId: PaneId): Promise<void> {\n if (!this.currentLayout) {\n return Promise.reject(new Error('There is no current layout selected, call start() first'));\n }\n\n if (!this.currentLayout.memberVideoPanes?.find((pane) => pane.id === paneId)) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in currentLayout.memberVideoPanes)`\n );\n\n return Promise.resolve();\n }\n\n if (!this.media.video.memberPanes[paneId]) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in this.media.video.memberPanes)`\n );\n\n return Promise.resolve();\n }\n\n const remoteMedia = this.media.video.memberPanes[paneId];\n\n const receiveSlot = remoteMedia.getUnderlyingReceiveSlot();\n\n if (receiveSlot) {\n this.receiveSlotManager.releaseSlot(receiveSlot);\n\n const index = this.slots.video.receiverSelected.indexOf(receiveSlot);\n\n if (index >= 0) {\n this.slots.video.receiverSelected.splice(index, 1);\n }\n }\n remoteMedia.stop();\n\n delete this.media.video.memberPanes[paneId];\n delete this.currentLayout.memberVideoPanes?.[paneId];\n\n return Promise.resolve();\n }\n\n /**\n * Pins an active speaker remote media object to the given CSI value. From that moment\n * onwards the remote media will only play audio/video from that specific CSI until\n * unpinActiveSpeakerVideoPane() is called or current layout is changed.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n * @param {CSI} csi CSI value to pin to, if undefined, then current CSI value is used\n */\n public pinActiveSpeakerVideoPane(remoteMedia: RemoteMedia, csi?: CSI): void {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'unpinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the unpinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.pin(remoteMedia, csi);\n }\n\n /**\n * Unpins a remote media object from the fixed CSI value it was pinned to.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n */\n public unpinActiveSpeakerVideoPane(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'pinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the pinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.unpin(remoteMedia);\n }\n\n /**\n * Returns true if a given remote media object belongs to an active speaker group and has been pinned.\n * Throws an error if the remote media object doesn't belong to any active speaker remote media group.\n *\n * @param {RemoteMedia} remoteMedia remote media object\n * @returns {boolean}\n */\n public isPinned(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia)\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among any remote media (pinned or unpinned) from any active speaker group'\n );\n }\n\n return remoteMediaGroup.isPinned(remoteMedia);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["AllEqualLayout","activeSpeakerVideoPaneGroups","id","numPanes","size","priority","SingleLayout","OnePlusFiveLayout","TwoMainPlusSixSmallLayout","RemoteScreenShareWithSmallThumbnailsLayout","screenShareVideo","Stage2x2With6ThumbnailsLayout","memberVideoPanes","csi","undefined","DefaultConfiguration","audio","numOfActiveSpeakerStreams","numOfScreenShareStreams","video","preferLiveVideo","initialLayoutId","layouts","AllEqual","OnePlusFive","Single","Stage","ScreenShareView","Event","RemoteMediaManager","receiveSlotManager","mediaRequestManagers","config","started","media","main","si","activeSpeakerGroups","memberPanes","screenShare","checkConfigValidity","slots","unused","activeSpeaker","receiverSelected","receiveSlotAllocations","LoggerProxy","logger","log","Error","forEach","layout","groupIds","paneIds","groupPriorites","group","pane","createAudioMedia","createScreenShareReceiveSlots","createScreenShareAudioMedia","preallocateVideoReceiveSlots","setLayout","invalidateCurrentRemoteMedia","screenShareAudio","commit","slot","releaseSlot","length","push","releaseUnusedVideoSlots","currentLayout","currentLayoutId","activeSpeakerCount","reduce","sum","paneGroup","receiverSelectedCount","maxNumVideoPanesRequired","maxValue","Math","max","getRequiredNumVideoSlotsForLayout","allocateSlot","MediaType","VideoMain","layoutId","updateVideoReceiveSlots","updateVideoRemoteMediaObjects","updateScreenShareVideoRemoteMediaObject","emitVideoLayoutChangedEvent","activeSpeakerGroup","setPreferLiveVideo","remoteMediaCsis","remoteMediaGroup","groupRemoteMediaCsis","filter","remoteMedia","includes","setActiveSpeakerCsis","mediaType","languageId","AudioMain","value","namedMediaGroup","type","NAMED_MEDIA_GROUP_TYPE_AUDIO","createInterpretationAudioMedia","setNamedMediaGroup","i","RemoteMediaGroup","emit","file","function","AudioCreated","commitRequest","InterpretationAudioCreated","AudioSlides","isAnyLayoutContainingScreenShareVideo","some","VideoSlides","ScreenShareAudioCreated","requiredCsis","memberVideoPane","isCsiNeededByCurrentLayout","notNeededReceiverSelectedSlots","sort","a","b","paneIndex","freeSlot","shift","memberPane","existingSlot","find","isExistingSlotAlreadyAllocated","pop","requiredNumSlots","totalNumSlots","numSlotsToCreate","logMessage","groupName","map","logString","join","key","logMainVideoReceiveSlots","logMainAudioReceiveSlots","logSlidesVideoReceiveSlots","logSlidesAudioReceiveSlots","trimActiveSpeakerSlots","trimReceiverSelectedSlots","refillRequiredSlotsIfNeeded","allocateSlotsToActiveSpeakerPaneGroups","allocateSlotsToReceiverSelectedVideoPaneGroups","groupId","paneGroupInCurrentLayout","groupInLayout","mediaGroup","resolution","warn","paneId","paneInCurrentLayout","paneInLayout","RemoteMedia","sendMediaRequest","options","stop","VideoLayoutChanged","activeSpeakerVideoPanes","getRemoteMedia","cancelMediaRequest","newPane","receiveSlot","reject","resolve","getUnderlyingReceiveSlot","index","indexOf","splice","pin","unpin","isPinned","EventsScope"],"sources":["remoteMediaManager.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\nimport {cloneDeep, forEach, remove} from 'lodash';\nimport {EventMap} from 'typed-emitter';\nimport {MediaType, NamedMediaGroup} from '@webex/internal-media-core';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nimport {RemoteMedia, RemoteVideoResolution} from './remoteMedia';\nimport {ReceiveSlot, CSI} from './receiveSlot';\nimport {ReceiveSlotManager} from './receiveSlotManager';\nimport {RemoteMediaGroup} from './remoteMediaGroup';\nimport {MediaRequestManager} from './mediaRequestManager';\nimport {NAMED_MEDIA_GROUP_TYPE_AUDIO} from '../constants';\n\nexport type PaneSize = RemoteVideoResolution;\nexport type LayoutId = string;\nexport type PaneId = string;\nexport type PaneGroupId = string;\n\nexport interface ActiveSpeakerVideoPaneGroup {\n id: PaneGroupId;\n numPanes: number; // maximum number of panes in the group (actual number may be lower, if there are not enough participants in the meeting)\n size: PaneSize; // preferred size for all panes in the group\n priority: number; // 0-255 (255 = highest priority), each group must have a different priority from all other groups\n}\n\nexport interface MemberVideoPane {\n id: PaneId;\n size: PaneSize;\n csi?: CSI;\n}\n\nexport interface VideoLayout {\n screenShareVideo?: {\n size: PaneSize;\n };\n activeSpeakerVideoPaneGroups?: ActiveSpeakerVideoPaneGroup[]; // list of active speaker video pane groups\n memberVideoPanes?: MemberVideoPane[]; // list of video panes for specific members, CSI values can be changed later via setVideoPaneCsi()\n}\n\nexport interface Configuration {\n audio: {\n numOfActiveSpeakerStreams: number; // number of audio streams we want to receive\n numOfScreenShareStreams: number; // 1 should be enough, because in webex only 1 person at a time can be presenting screen share\n };\n video: {\n preferLiveVideo: boolean; // applies to all pane groups with active speaker policy\n initialLayoutId: LayoutId;\n\n layouts: {[key: LayoutId]: VideoLayout}; // a map of all available layouts, a layout can be set via setLayout() method\n };\n namedMediaGroup?: NamedMediaGroup;\n}\n\n/* Predefined layouts: */\n\n// An \"all equal\" grid, with size up to 3 x 3 = 9:\nconst AllEqualLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 9,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with just a single remote active speaker video pane:\nconst SingleLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'main',\n numPanes: 1,\n size: 'best',\n priority: 255,\n },\n ],\n};\n\n// A layout with 1 big pane for the highest priority active speaker and 5 small panes for other active speakers:\nconst OnePlusFiveLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainBigOne',\n numPanes: 1,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondarySetOfSmallPanes',\n numPanes: 5,\n size: 'very small',\n priority: 254,\n },\n ],\n};\n\n// A layout with 2 big panes for 2 main active speakers and a strip of 6 small panes for other active speakers:\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst TwoMainPlusSixSmallLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'mainGroupWith2BigPanes',\n numPanes: 2,\n size: 'large',\n priority: 255,\n },\n {\n id: 'secondaryGroupOfSmallPanes',\n numPanes: 6,\n size: 'small',\n priority: 254,\n },\n ],\n};\n\n// A strip of 8 small video panes (thumbnails) displayed at the top of a remote screenshare:\nconst RemoteScreenShareWithSmallThumbnailsLayout: VideoLayout = {\n screenShareVideo: {size: 'best'},\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 8,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n};\n\n// A staged layout with 4 pre-selected meeting participants in the main 2x2 grid and 6 small panes for other active speakers at the top:\nconst Stage2x2With6ThumbnailsLayout: VideoLayout = {\n activeSpeakerVideoPaneGroups: [\n {\n id: 'thumbnails',\n numPanes: 6,\n size: 'thumbnail',\n priority: 255,\n },\n ],\n memberVideoPanes: [\n {id: 'stage-1', size: 'medium', csi: undefined},\n {id: 'stage-2', size: 'medium', csi: undefined},\n {id: 'stage-3', size: 'medium', csi: undefined},\n {id: 'stage-4', size: 'medium', csi: undefined},\n ],\n};\n\n/**\n * Default configuration:\n * - uses 3 audio streams\n * - prefers active speakers with live video (e.g. are not audio only or video muted) over active speakers without live video\n * - has a few layouts defined, including 1 that contains remote screen share (ScreenShareView)\n */\nexport const DefaultConfiguration: Configuration = {\n audio: {\n numOfActiveSpeakerStreams: 3,\n numOfScreenShareStreams: 1,\n },\n video: {\n preferLiveVideo: true,\n initialLayoutId: 'AllEqual',\n\n layouts: {\n AllEqual: AllEqualLayout,\n OnePlusFive: OnePlusFiveLayout,\n Single: SingleLayout,\n Stage: Stage2x2With6ThumbnailsLayout,\n ScreenShareView: RemoteScreenShareWithSmallThumbnailsLayout,\n },\n },\n};\n\nexport enum Event {\n // events for audio streams\n AudioCreated = 'AudioCreated',\n InterpretationAudioCreated = 'InterpretationAudioCreated',\n ScreenShareAudioCreated = 'ScreenShareAudioCreated',\n\n // events for video streams\n VideoLayoutChanged = 'VideoLayoutChanged',\n}\n\nexport interface VideoLayoutChangedEventData {\n layoutId: LayoutId;\n activeSpeakerVideoPanes: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberVideoPanes: {[key: PaneId]: RemoteMedia};\n screenShareVideo?: RemoteMedia;\n}\nexport interface Events extends EventMap {\n // audio\n [Event.AudioCreated]: (audio: RemoteMediaGroup) => void;\n [Event.ScreenShareAudioCreated]: (screenShareAudio: RemoteMediaGroup) => void;\n\n // video\n [Event.VideoLayoutChanged]: (data: VideoLayoutChangedEventData) => void;\n}\n\n/**\n * A helper class that manages all remote audio/video streams in order to achieve a predefined set of layouts.\n * It also creates a fixed number of audio streams and these don't change during the meeting.\n *\n * Things that RemoteMediaManager does:\n * - owns the receive slots (creates them when needed, and re-uses them when switching layouts)\n * - constructs appropriate RemoteMedia and RemoteMediaGroup objects and sends appropriate mediaRequests\n */\nexport class RemoteMediaManager extends EventsScope {\n private config: Configuration;\n\n private started: boolean;\n\n private receiveSlotManager: ReceiveSlotManager;\n\n private mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n screenShareAudio: MediaRequestManager;\n screenShareVideo: MediaRequestManager;\n };\n\n private currentLayout?: VideoLayout;\n\n private slots: {\n audio: {\n main: ReceiveSlot[];\n si: ReceiveSlot;\n };\n screenShare: {\n audio: ReceiveSlot[];\n video?: ReceiveSlot;\n };\n video: {\n unused: ReceiveSlot[];\n activeSpeaker: ReceiveSlot[];\n receiverSelected: ReceiveSlot[];\n };\n };\n\n private media: {\n audio: {\n main?: RemoteMediaGroup;\n si?: RemoteMediaGroup;\n };\n video: {\n activeSpeakerGroups: {\n [key: PaneGroupId]: RemoteMediaGroup;\n };\n memberPanes: {[key: PaneId]: RemoteMedia};\n };\n screenShare: {\n audio?: RemoteMediaGroup;\n video?: RemoteMediaGroup;\n };\n };\n\n private receiveSlotAllocations: {\n activeSpeaker: {[key: PaneGroupId]: {slots: ReceiveSlot[]}};\n receiverSelected: {[key: PaneId]: ReceiveSlot};\n };\n\n private currentLayoutId?: LayoutId;\n\n /**\n * Constructor\n *\n * @param {ReceiveSlotManager} receiveSlotManager\n * @param {{audio: MediaRequestManager, video: mediaRequestManagers}} mediaRequestManagers\n * @param {Configuration} config Configuration describing what video layouts to use during the meeting\n */\n constructor(\n receiveSlotManager: ReceiveSlotManager,\n mediaRequestManagers: {\n audio: MediaRequestManager;\n video: MediaRequestManager;\n screenShareAudio: MediaRequestManager;\n screenShareVideo: MediaRequestManager;\n },\n config: Configuration = DefaultConfiguration\n ) {\n super();\n this.started = false;\n this.config = config;\n this.receiveSlotManager = receiveSlotManager;\n this.mediaRequestManagers = mediaRequestManagers;\n this.media = {\n audio: {\n main: undefined,\n si: undefined,\n },\n video: {\n activeSpeakerGroups: {},\n memberPanes: {},\n },\n screenShare: {\n audio: undefined,\n video: undefined,\n },\n };\n\n this.checkConfigValidity();\n\n this.slots = {\n audio: {\n main: [],\n si: undefined,\n },\n screenShare: {\n audio: [],\n video: undefined,\n },\n video: {\n unused: [],\n activeSpeaker: [],\n receiverSelected: [],\n },\n };\n\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#constructor --> RemoteMediaManager created with config: ${JSON.stringify(\n this.config\n )}`\n );\n }\n\n /**\n * Checks if configuration is valid, throws an error if it's not\n */\n private checkConfigValidity() {\n if (!(this.config.video.initialLayoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid config: initialLayoutId \"${this.config.video.initialLayoutId}\" doesn't match any of the layouts`\n );\n }\n\n // check if each layout is valid\n Object.values(this.config.video.layouts).forEach((layout) => {\n const groupIds = {};\n const paneIds = {};\n const groupPriorites = {};\n\n layout.activeSpeakerVideoPaneGroups?.forEach((group) => {\n if (groupIds[group.id]) {\n throw new Error(\n `invalid config: duplicate active speaker video pane group id: ${group.id}`\n );\n }\n groupIds[group.id] = true;\n\n if (groupPriorites[group.priority]) {\n throw new Error(\n `invalid config: multiple active speaker video pane groups have same priority: ${group.priority}`\n );\n }\n groupPriorites[group.priority] = true;\n });\n\n layout.memberVideoPanes?.forEach((pane) => {\n if (paneIds[pane.id]) {\n throw new Error(`invalid config: duplicate member video pane id: ${pane.id}`);\n }\n paneIds[pane.id] = true;\n });\n });\n }\n\n /**\n * Starts the RemoteMediaManager.\n *\n * @returns {Promise}\n */\n public async start() {\n if (this.started) {\n throw new Error('start() failure: already started');\n }\n this.started = true;\n\n await this.createAudioMedia();\n\n await this.createScreenShareReceiveSlots();\n this.createScreenShareAudioMedia();\n\n await this.preallocateVideoReceiveSlots();\n\n await this.setLayout(this.config.video.initialLayoutId);\n }\n\n /**\n * Releases all the used resources (like allocated receive slots). This function needs\n * to be called when we leave the meeting, etc.\n */\n public stop() {\n // invalidate all remoteMedia objects\n this.invalidateCurrentRemoteMedia({\n audio: true,\n video: true,\n screenShareAudio: true,\n screenShareVideo: true,\n commit: true,\n });\n\n // release all audio receive slots\n this.slots.audio.main.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.audio.main.length = 0;\n if (this.slots.audio.si) {\n this.receiveSlotManager.releaseSlot(this.slots.audio.si);\n }\n\n // release screen share slots\n this.slots.screenShare.audio.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.screenShare.audio.length = 0;\n if (this.slots.screenShare.video) {\n this.receiveSlotManager.releaseSlot(this.slots.screenShare.video);\n this.slots.screenShare.video = undefined;\n }\n\n // release video slots\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n\n this.slots.video.unused.push(...this.slots.video.receiverSelected);\n this.slots.video.receiverSelected.length = 0;\n\n this.releaseUnusedVideoSlots();\n\n this.currentLayout = undefined;\n this.currentLayoutId = undefined;\n this.started = false;\n }\n\n /**\n * Returns the total number of main video panes required for a given layout\n *\n * @param {VideoLayout} layout\n * @returns {number}\n */\n private getRequiredNumVideoSlotsForLayout(layout?: VideoLayout) {\n if (!layout) {\n return 0;\n }\n\n const activeSpeakerCount =\n layout.activeSpeakerVideoPaneGroups?.reduce(\n (sum, paneGroup) => sum + paneGroup.numPanes,\n 0\n ) || 0;\n\n const receiverSelectedCount = layout.memberVideoPanes?.length || 0;\n\n return activeSpeakerCount + receiverSelectedCount;\n }\n\n /**\n * Allocates the maximum number of panes that any of the configured layouts will require.\n * We do this at the beginning, because it's more efficient (much faster) then allocating receive slots\n * later, after the SDP exchange was done.\n */\n private async preallocateVideoReceiveSlots() {\n const maxNumVideoPanesRequired = Object.values(this.config.video.layouts).reduce(\n (maxValue, layout) => Math.max(maxValue, this.getRequiredNumVideoSlotsForLayout(layout)),\n 0\n );\n\n while (this.slots.video.unused.length < maxNumVideoPanesRequired) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n // eslint-disable-next-line no-await-in-loop\n await this.receiveSlotManager.allocateSlot(MediaType.VideoMain)\n );\n }\n }\n\n /**\n * Changes the layout (triggers Event.VideoLayoutChanged)\n *\n * @param {LayoutId} layoutId new layout id\n * @returns {Promise}\n */\n public async setLayout(layoutId: LayoutId) {\n if (!(layoutId in this.config.video.layouts)) {\n throw new Error(\n `invalid layoutId: \"${layoutId}\" doesn't match any of the configured layouts`\n );\n }\n if (!this.started) {\n throw new Error('setLayout() called before start()');\n }\n LoggerProxy.logger.log(`RemoteMediaManager#setLayout --> new layout selected: ${layoutId}`);\n\n this.currentLayoutId = layoutId;\n this.currentLayout = cloneDeep(this.config.video.layouts[this.currentLayoutId]);\n\n await this.updateVideoReceiveSlots();\n this.updateVideoRemoteMediaObjects();\n this.updateScreenShareVideoRemoteMediaObject();\n this.emitVideoLayoutChangedEvent();\n }\n\n /**\n * Returns the currently selected layout id\n *\n * @returns {LayoutId}\n */\n public getLayoutId(): LayoutId | undefined {\n return this.currentLayoutId;\n }\n\n /**\n * sets the preferLiveVideo\n */\n public setPreferLiveVideo(preferLiveVideo: boolean) {\n LoggerProxy.logger.log(\n `RemoteMediaManager#setPreferLiveVideo --> setPreferLiveVideo is called to set preferLiveVideo to ${preferLiveVideo}`\n );\n this.config.video.preferLiveVideo = preferLiveVideo;\n Object.values(this.media.video.activeSpeakerGroups).forEach((activeSpeakerGroup) => {\n activeSpeakerGroup.setPreferLiveVideo(preferLiveVideo, false);\n });\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Sets CSIs for multiple RemoteMedia instances belonging to RemoteMediaGroup.\n * For each entry in the remoteMediaCsis array:\n * - if csi is specified, the RemoteMedia instance is pinned to that CSI\n * - if csi is undefined, the RemoteMedia instance is unpinned\n */\n public setActiveSpeakerCsis(remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: number}[]) {\n Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {\n const groupRemoteMediaCsis = remoteMediaCsis.filter(({remoteMedia}) =>\n remoteMediaGroup.includes(remoteMedia)\n );\n if (groupRemoteMediaCsis.length > 0) {\n remoteMediaGroup.setActiveSpeakerCsis(groupRemoteMediaCsis, false);\n }\n });\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Sets which named media group need receiving\n * @param {MediaType} mediaType of the stream\n * @param {number} languageCode of the stream. If the languageId is 0, the named media group request will be canceled,\n * and only receive the main audio stream.\n * @returns {void}\n */\n public async setReceiveNamedMediaGroup(mediaType: MediaType, languageId: number) {\n if (mediaType !== MediaType.AudioMain) {\n throw new Error(`cannot set receive named media group which media type is ${mediaType}`);\n }\n\n const value = languageId;\n if (value === this.config.namedMediaGroup?.value) {\n return;\n }\n\n this.config.namedMediaGroup = {\n type: NAMED_MEDIA_GROUP_TYPE_AUDIO,\n value,\n };\n\n if (!this.media.audio.si) {\n await this.createInterpretationAudioMedia(true);\n } else {\n this.media.audio.si.setNamedMediaGroup(this.config.namedMediaGroup, true);\n }\n }\n\n /**\n * Creates the audio slots\n */\n private async createAudioMedia() {\n // create si audio request\n await this.createInterpretationAudioMedia(false);\n\n // create main audio receive slots\n for (let i = 0; i < this.config.audio.numOfActiveSpeakerStreams; i += 1) {\n // eslint-disable-next-line no-await-in-loop\n const slot = await this.receiveSlotManager.allocateSlot(MediaType.AudioMain);\n\n this.slots.audio.main.push(slot);\n }\n\n // create a remote media group for main audio\n this.media.audio.main = new RemoteMediaGroup(\n this.mediaRequestManagers.audio,\n this.slots.audio.main,\n 255,\n true\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createAudioMedia'},\n Event.AudioCreated,\n this.media.audio.main\n );\n }\n\n /**\n * Creates the audio slots for named media\n */\n private async createInterpretationAudioMedia(commitRequest: boolean) {\n // create slot for interpretation language audio\n if (\n this.config.namedMediaGroup?.type === NAMED_MEDIA_GROUP_TYPE_AUDIO &&\n this.config.namedMediaGroup?.value\n ) {\n this.slots.audio.si = await this.receiveSlotManager.allocateSlot(MediaType.AudioMain);\n\n // create a remote media group for si audio\n this.media.audio.si = new RemoteMediaGroup(\n this.mediaRequestManagers.audio,\n [this.slots.audio.si],\n 255,\n commitRequest,\n {\n namedMediaGroup: this.config.namedMediaGroup,\n }\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createInterpretationAudioMedia'},\n Event.InterpretationAudioCreated,\n this.media.audio.si\n );\n }\n }\n\n /**\n * Creates receive slots required for receiving screen share audio and video\n */\n private async createScreenShareReceiveSlots() {\n // audio\n for (let i = 0; i < this.config.audio.numOfScreenShareStreams; i += 1) {\n // eslint-disable-next-line no-await-in-loop\n const slot = await this.receiveSlotManager.allocateSlot(MediaType.AudioSlides);\n\n this.slots.screenShare.audio.push(slot);\n }\n\n // video\n const isAnyLayoutContainingScreenShareVideo = Object.values(this.config.video.layouts).some(\n (layout) => !!layout.screenShareVideo\n );\n\n if (isAnyLayoutContainingScreenShareVideo) {\n this.slots.screenShare.video = await this.receiveSlotManager.allocateSlot(\n MediaType.VideoSlides\n );\n }\n }\n\n /**\n * Creates RemoteMedia objects for screen share\n */\n private createScreenShareAudioMedia() {\n if (this.slots.screenShare.audio.length > 0) {\n this.media.screenShare.audio = new RemoteMediaGroup(\n this.mediaRequestManagers.screenShareAudio,\n this.slots.screenShare.audio,\n 255,\n true\n );\n\n this.emit(\n {file: 'multistream/remoteMediaManager', function: 'createScreenShareAudioMedia'},\n Event.ScreenShareAudioCreated,\n this.media.screenShare.audio\n );\n }\n }\n\n /**\n * Goes over all receiver-selected slots and keeps only the ones that are required by a given layout,\n * the rest are all moved to the \"unused\" list\n */\n private trimReceiverSelectedSlots() {\n const requiredCsis = {};\n\n // fill requiredCsis with all the CSIs that the given layout requires\n this.currentLayout?.memberVideoPanes?.forEach((memberVideoPane) => {\n if (memberVideoPane.csi !== undefined) {\n requiredCsis[memberVideoPane.csi] = true;\n }\n });\n\n const isCsiNeededByCurrentLayout = (csi?: CSI): boolean => {\n if (csi === undefined) {\n return false;\n }\n\n return !!requiredCsis[csi];\n };\n\n // keep receiverSelected slots that match our new requiredCsis, move the rest of receiverSelected slots to unused\n const notNeededReceiverSelectedSlots = remove(\n this.slots.video.receiverSelected,\n (slot) => isCsiNeededByCurrentLayout(slot.csi) === false\n );\n\n this.slots.video.unused.push(...notNeededReceiverSelectedSlots);\n }\n\n /**\n * Releases all the \"unused\" video slots.\n */\n private releaseUnusedVideoSlots() {\n this.slots.video.unused.forEach((slot) => this.receiveSlotManager.releaseSlot(slot));\n this.slots.video.unused.length = 0;\n }\n\n /**\n * Allocates receive slots to all active speaker video panes\n * in the current selected layout.\n *\n * Allocation tries to keep the same order of the slots between the previous\n * layout and the new one. Sorting helps making sure that highest priority slots\n * go in the same order in the new layout.\n */\n private allocateSlotsToActiveSpeakerPaneGroups() {\n this.currentLayout?.activeSpeakerVideoPaneGroups\n // sorting in descending order based on group priority\n ?.sort((a, b) => (a.priority < b.priority ? 1 : -1))\n ?.forEach((group) => {\n this.receiveSlotAllocations.activeSpeaker[group.id] = {slots: []};\n\n for (let paneIndex = 0; paneIndex < group.numPanes; paneIndex += 1) {\n // allocate a slot from the \"unused\" list, by grabbing in same order (shift) as previous layout\n const freeSlot = this.slots.video.unused.shift();\n\n if (freeSlot) {\n this.slots.video.activeSpeaker.push(freeSlot);\n this.receiveSlotAllocations.activeSpeaker[group.id].slots.push(freeSlot);\n }\n }\n });\n }\n\n /**\n * Allocates receive slots to all receiver selected video panes\n * in the current selected layout\n */\n private allocateSlotsToReceiverSelectedVideoPaneGroups() {\n this.currentLayout?.memberVideoPanes?.forEach((memberPane) => {\n // check if there is existing slot for this csi\n const existingSlot = this.slots.video.receiverSelected.find(\n (slot) => slot.csi === memberPane.csi\n );\n\n const isExistingSlotAlreadyAllocated = Object.values(\n this.receiveSlotAllocations.receiverSelected\n ).includes(existingSlot);\n\n if (memberPane.csi !== undefined && existingSlot && !isExistingSlotAlreadyAllocated) {\n // found it, so use it\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = existingSlot;\n } else {\n // allocate a slot from the \"unused\" list\n const freeSlot = this.slots.video.unused.pop();\n\n if (freeSlot) {\n this.slots.video.receiverSelected.push(freeSlot);\n this.receiveSlotAllocations.receiverSelected[memberPane.id] = freeSlot;\n }\n }\n });\n }\n\n /**\n * Ensures that we have enough slots for the current layout.\n */\n private async refillRequiredSlotsIfNeeded() {\n const requiredNumSlots = this.getRequiredNumVideoSlotsForLayout(this.currentLayout);\n const totalNumSlots =\n this.slots.video.unused.length +\n this.slots.video.activeSpeaker.length +\n this.slots.video.receiverSelected.length;\n\n if (totalNumSlots < requiredNumSlots) {\n let numSlotsToCreate = requiredNumSlots - totalNumSlots;\n\n while (numSlotsToCreate > 0) {\n // eslint-disable-next-line no-await-in-loop\n this.slots.video.unused.push(\n // eslint-disable-next-line no-await-in-loop\n await this.receiveSlotManager.allocateSlot(MediaType.VideoMain)\n );\n numSlotsToCreate -= 1;\n }\n }\n }\n\n /**\n * Move all active speaker slots to \"unused\"\n */\n private trimActiveSpeakerSlots() {\n this.slots.video.unused.push(...this.slots.video.activeSpeaker);\n this.slots.video.activeSpeaker.length = 0;\n }\n\n /**\n * Logs the state of the receive slots\n */\n private logMainVideoReceiveSlots() {\n let logMessage = '';\n forEach(this.receiveSlotAllocations.activeSpeaker, (group, groupName) => {\n logMessage += `\\ngroup: ${groupName}\\n${group.slots\n .map((slot) => slot.logString)\n .join(', ')}`;\n });\n\n logMessage += '\\nreceiverSelected:\\n';\n forEach(this.receiveSlotAllocations.receiverSelected, (slot, key) => {\n logMessage += ` ${key}: ${slot.logString}\\n`;\n });\n\n LoggerProxy.logger.log(\n `RemoteMediaManager#logMainVideoReceiveSlots --> MAIN VIDEO receive slots: unused=${this.slots.video.unused.length}, activeSpeaker=${this.slots.video.activeSpeaker.length}, receiverSelected=${this.slots.video.receiverSelected.length}${logMessage}`\n );\n }\n\n /** logs main audio slots */\n private logMainAudioReceiveSlots() {\n LoggerProxy.logger.log(\n `RemoteMediaManager#logMainAudioReceiveSlots --> MAIN AUDIO receive slots: ${this.slots.audio.main\n .map((slot) => slot.logString)\n .join(', ')}`\n );\n }\n\n /** logs slides video slots */\n private logSlidesVideoReceiveSlots() {\n LoggerProxy.logger.log(\n `RemoteMediaManager#logSlidesVideoReceiveSlots --> SLIDES VIDEO receive slot: ${this.slots.screenShare.video?.logString}`\n );\n }\n\n /** logs slides audio slots */\n private logSlidesAudioReceiveSlots() {\n LoggerProxy.logger.log(\n `RemoteMediaManager#logSlidesAudioReceiveSlots --> SLIDES AUDIO receive slots: ${this.slots.screenShare.audio\n .map((slot) => slot.logString)\n .join(', ')}`\n );\n }\n\n /** Logs all current receive slots */\n public logAllReceiveSlots() {\n this.logMainVideoReceiveSlots();\n this.logMainAudioReceiveSlots();\n this.logSlidesVideoReceiveSlots();\n this.logSlidesAudioReceiveSlots();\n }\n\n /**\n * Makes sure we have the right number of receive slots created for the current layout\n * and allocates them to the right video panes / pane groups\n *\n * @returns {Promise}\n */\n private async updateVideoReceiveSlots() {\n // move all active speaker slots to \"unused\"\n this.trimActiveSpeakerSlots();\n\n // move all no longer needed receiver-selected slots to \"unused\"\n this.trimReceiverSelectedSlots();\n\n // ensure we have enough total slots for current layout\n await this.refillRequiredSlotsIfNeeded();\n\n // allocate the slots to the right panes / pane groups\n // reset allocations\n this.receiveSlotAllocations = {activeSpeaker: {}, receiverSelected: {}};\n // allocate active speaker\n this.allocateSlotsToActiveSpeakerPaneGroups();\n // allocate receiver selected\n this.allocateSlotsToReceiverSelectedVideoPaneGroups();\n\n this.logMainVideoReceiveSlots();\n\n // If this is the initial layout, there may be some \"unused\" slots left because of the preallocation\n // done in this.preallocateVideoReceiveSlots(), so release them now\n this.releaseUnusedVideoSlots();\n }\n\n /**\n * Creates new RemoteMedia and RemoteMediaGroup objects for the current layout\n * and sends the media requests for all of them.\n */\n private updateVideoRemoteMediaObjects() {\n // invalidate all the previous remote media objects and cancel their media requests\n this.invalidateCurrentRemoteMedia({\n audio: false,\n video: true,\n screenShareAudio: false,\n screenShareVideo: false,\n commit: false,\n });\n\n // create new remoteMediaGroup objects\n this.media.video.activeSpeakerGroups = {};\n this.media.video.memberPanes = {};\n\n for (const [groupId, group] of Object.entries(this.receiveSlotAllocations.activeSpeaker)) {\n const paneGroupInCurrentLayout = this.currentLayout?.activeSpeakerVideoPaneGroups?.find(\n (groupInLayout) => groupInLayout.id === groupId\n );\n\n if (paneGroupInCurrentLayout) {\n const mediaGroup = new RemoteMediaGroup(\n this.mediaRequestManagers.video,\n group.slots,\n paneGroupInCurrentLayout.priority,\n false,\n {\n preferLiveVideo: this.config.video.preferLiveVideo,\n resolution: paneGroupInCurrentLayout.size,\n }\n );\n\n this.media.video.activeSpeakerGroups[groupId] = mediaGroup;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a group id ${groupId} from this.receiveSlotAllocations.activeSpeaker cannot be found in the current layout configuration`\n );\n }\n }\n\n // create new remoteMedia objects\n for (const [paneId, slot] of Object.entries(this.receiveSlotAllocations.receiverSelected)) {\n const paneInCurrentLayout = this.currentLayout?.memberVideoPanes?.find(\n (paneInLayout) => paneInLayout.id === paneId\n );\n\n if (paneInCurrentLayout) {\n const remoteMedia = new RemoteMedia(slot, this.mediaRequestManagers.video, {\n resolution: paneInCurrentLayout.size,\n });\n\n if (paneInCurrentLayout.csi) {\n remoteMedia.sendMediaRequest(paneInCurrentLayout.csi, false);\n }\n\n this.media.video.memberPanes[paneId] = remoteMedia;\n } else {\n // this should never happen, because this.receiveSlotAllocations are created based on current layout configuration\n LoggerProxy.logger.warn(\n `a pane id ${paneId} from this.receiveSlotAllocations.receiverSelected cannot be found in the current layout configuration`\n );\n }\n }\n\n this.mediaRequestManagers.video.commit();\n }\n\n /**\n * Checks if current layout requires a screen share.\n * If it does, it creates new RemoteMediaGroup object for screen share\n * and sends the media requests for it.\n * If it doesn't, it makes sure we clean up any RemoteMediaGroup objects\n * created earlier for screen share (for previous layout).\n */\n private updateScreenShareVideoRemoteMediaObject() {\n this.invalidateCurrentRemoteMedia({\n audio: false,\n video: false,\n screenShareAudio: false,\n screenShareVideo: true,\n commit: false,\n });\n\n this.media.screenShare.video = undefined;\n\n if (this.currentLayout?.screenShareVideo) {\n // we create a group of 1, because for screen share we need to use the \"active speaker\" policy\n this.media.screenShare.video = new RemoteMediaGroup(\n this.mediaRequestManagers.screenShareVideo,\n [this.slots.screenShare.video],\n 255,\n false,\n {resolution: this.currentLayout.screenShareVideo.size}\n );\n }\n\n this.mediaRequestManagers.screenShareVideo.commit();\n }\n\n /**\n * Invalidates all remote media objects belonging to currently selected layout\n */\n private invalidateCurrentRemoteMedia(options: {\n audio: boolean;\n video: boolean;\n screenShareAudio: boolean;\n screenShareVideo: boolean;\n commit: boolean;\n }) {\n const {audio, video, screenShareAudio, screenShareVideo, commit} = options;\n\n if (audio) {\n if (this.media.audio.main) {\n this.media.audio.main.stop(commit);\n }\n if (this.media.audio.si) {\n this.media.audio.si.stop(commit);\n }\n }\n if (video) {\n Object.values(this.media.video.activeSpeakerGroups).forEach((remoteMediaGroup) => {\n remoteMediaGroup.stop(false);\n });\n Object.values(this.media.video.memberPanes).forEach((remoteMedia) => {\n remoteMedia.stop(false);\n });\n if (commit) {\n this.mediaRequestManagers.video.commit();\n }\n }\n\n if (screenShareAudio && this.media.screenShare.audio) {\n this.media.screenShare.audio.stop(commit);\n }\n if (screenShareVideo && this.media.screenShare.video) {\n this.media.screenShare.video.stop(commit);\n }\n }\n\n /** emits Event.VideoLayoutChanged */\n private emitVideoLayoutChangedEvent() {\n // todo: at this point the receive slots might still be showing a participant from previous layout, we should\n // wait for our media requests to be fulfilled, but there is no API for that right now (we could wait for source updates\n // but in some cases they might never come, or would need to always make sure to use a new set of receiver slots)\n // for now it's fine to have it like this, we will re-evaluate if it needs improving after more testing\n\n this.emit(\n {\n file: 'multistream/remoteMediaManager',\n function: 'emitVideoLayoutChangedEvent',\n },\n Event.VideoLayoutChanged,\n {\n layoutId: this.currentLayoutId,\n activeSpeakerVideoPanes: this.media.video.activeSpeakerGroups,\n memberVideoPanes: this.media.video.memberPanes,\n screenShareVideo: this.media.screenShare.video?.getRemoteMedia()[0],\n }\n );\n }\n\n /**\n * Sets a new CSI on a given remote media object\n *\n * @param {RemoteMedia} remoteMedia remote Media object to modify\n * @param {CSI} csi new CSI value, can be null if we want to stop receiving media\n */\n public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi: CSI | null) {\n if (!Object.values(this.media.video.memberPanes).includes(remoteMedia)) {\n throw new Error('remoteMedia not found');\n }\n\n if (csi) {\n remoteMedia.sendMediaRequest(csi, true);\n } else {\n remoteMedia.cancelMediaRequest(true);\n }\n }\n\n /**\n * Adds a new member video pane to the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {MemberVideoPane} newPane\n * @returns {Promise<RemoteMedia>}\n */\n public async addMemberVideoPane(newPane: MemberVideoPane): Promise<RemoteMedia> {\n if (!this.currentLayout) {\n throw new Error('There is no current layout selected, call start() first');\n }\n\n if (!this.currentLayout?.memberVideoPanes) {\n this.currentLayout.memberVideoPanes = [];\n }\n\n if (newPane.id in this.currentLayout.memberVideoPanes) {\n throw new Error(\n `duplicate pane id ${newPane.id} - this pane already exists in current layout's memberVideoPanes`\n );\n }\n\n this.currentLayout.memberVideoPanes.push(newPane);\n\n const receiveSlot = await this.receiveSlotManager.allocateSlot(MediaType.VideoMain);\n\n this.slots.video.receiverSelected.push(receiveSlot);\n\n const remoteMedia = new RemoteMedia(receiveSlot, this.mediaRequestManagers.video, {\n resolution: newPane.size,\n });\n\n if (newPane.csi) {\n remoteMedia.sendMediaRequest(newPane.csi, true);\n }\n\n this.media.video.memberPanes[newPane.id] = remoteMedia;\n\n return remoteMedia;\n }\n\n /**\n * Removes a member video pane from the currently selected layout.\n *\n * Changes to the layout are lost after a layout change.\n *\n * @param {PaneId} paneId pane id of the pane to remove\n * @returns {Promise<void>}\n */\n public removeMemberVideoPane(paneId: PaneId): Promise<void> {\n if (!this.currentLayout) {\n return Promise.reject(new Error('There is no current layout selected, call start() first'));\n }\n\n if (!this.currentLayout.memberVideoPanes?.find((pane) => pane.id === paneId)) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in currentLayout.memberVideoPanes)`\n );\n\n return Promise.resolve();\n }\n\n if (!this.media.video.memberPanes[paneId]) {\n // pane id doesn't exist, so nothing to do\n LoggerProxy.logger.log(\n `RemoteMediaManager#removeMemberVideoPane --> removeMemberVideoPane() called for a non-existent paneId: ${paneId} (pane not found in this.media.video.memberPanes)`\n );\n\n return Promise.resolve();\n }\n\n const remoteMedia = this.media.video.memberPanes[paneId];\n\n const receiveSlot = remoteMedia.getUnderlyingReceiveSlot();\n\n if (receiveSlot) {\n this.receiveSlotManager.releaseSlot(receiveSlot);\n\n const index = this.slots.video.receiverSelected.indexOf(receiveSlot);\n\n if (index >= 0) {\n this.slots.video.receiverSelected.splice(index, 1);\n }\n }\n remoteMedia.stop();\n\n delete this.media.video.memberPanes[paneId];\n delete this.currentLayout.memberVideoPanes?.[paneId];\n\n return Promise.resolve();\n }\n\n /**\n * Pins an active speaker remote media object to the given CSI value. From that moment\n * onwards the remote media will only play audio/video from that specific CSI until\n * unpinActiveSpeakerVideoPane() is called or current layout is changed.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n * @param {CSI} csi CSI value to pin to, if undefined, then current CSI value is used\n */\n public pinActiveSpeakerVideoPane(remoteMedia: RemoteMedia, csi?: CSI): void {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'unpinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the unpinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.pin(remoteMedia, csi);\n }\n\n /**\n * Unpins a remote media object from the fixed CSI value it was pinned to.\n *\n * @param {RemoteMedia} remoteMedia remote media object reference\n */\n public unpinActiveSpeakerVideoPane(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia, 'pinned')\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among the pinned remote media from any active speaker group'\n );\n }\n\n remoteMediaGroup.unpin(remoteMedia);\n }\n\n /**\n * Returns true if a given remote media object belongs to an active speaker group and has been pinned.\n * Throws an error if the remote media object doesn't belong to any active speaker remote media group.\n *\n * @param {RemoteMedia} remoteMedia remote media object\n * @returns {boolean}\n */\n public isPinned(remoteMedia: RemoteMedia) {\n const remoteMediaGroup = Object.values(this.media.video.activeSpeakerGroups).find((group) =>\n group.includes(remoteMedia)\n );\n\n if (!remoteMediaGroup) {\n throw new Error(\n 'remoteMedia not found among any remote media (pinned or unpinned) from any active speaker group'\n );\n }\n\n return remoteMediaGroup.isPinned(remoteMedia);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["SendSlotManager","LoggerProxy","mediaConnection","mediaType","active","slots","has","Error","slot","createSendSlot","set","logger","info","get","namedMediaGroups","MediaType","AudioMain","setNamedMediaGroups","stream","publishStream","label","muted","unpublishStream","codecParameters","setCodecParameters","parameters","deleteCodecParameters","clear"],"sources":["sendSlotManager.ts"],"sourcesContent":["import {\n SendSlot,\n MediaType,\n LocalStream,\n MultistreamRoapMediaConnection,\n} from '@webex/internal-media-core';\n\nimport {NamedMediaGroup} from '@webex/json-multistream';\n\nexport default class SendSlotManager {\n private readonly slots: Map<MediaType, SendSlot> = new Map();\n private readonly LoggerProxy: any;\n\n constructor(LoggerProxy: any) {\n this.LoggerProxy = LoggerProxy;\n }\n\n /**\n * This method is used to create a sendSlot for the given mediaType and returns the created sendSlot\n * @param {MultistreamRoapMediaConnection} mediaConnection MultistreamRoapMediaConnection for which a sendSlot needs to be created\n * @param {MediaType} mediaType MediaType for which a sendSlot needs to be created (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {boolean} active This is optional boolean to set the active state of the sendSlot. Default is true\n * @returns {SendSlot} slot The created sendSlot\n */\n public createSlot(\n mediaConnection: MultistreamRoapMediaConnection,\n mediaType: MediaType,\n active = true\n ): SendSlot {\n if (this.slots.has(mediaType)) {\n throw new Error(`Slot for ${mediaType} already exists`);\n }\n\n const slot: SendSlot = mediaConnection.createSendSlot(mediaType, active);\n\n this.slots.set(mediaType, slot);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->createSlot#Created slot for ${mediaType} with active ${active}`\n );\n\n return slot;\n }\n\n /**\n * This method is used to retrieve the sendSlot for the given mediaType\n * @param {MediaType} mediaType of which the slot needs to be retrieved\n * @returns {SendSlot}\n */\n public getSlot(mediaType: MediaType): SendSlot {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n return slot;\n }\n\n /**\n * Allow users to specify 'namedMediaGroups' to indicate which named media group its audio should be sent to.\n * @param {MediaType} mediaType MediaType of the sendSlot to which the audio stream needs to be send to the media group\n * @param {[]}namedMediaGroups - Allow users to specify 'namedMediaGroups'.If the value of 'namedMediaGroups' is zero,\n * named media group will be canceled and the audio stream will be sent to the floor.\n * @returns {void}\n */\n public setNamedMediaGroups(mediaType: MediaType, namedMediaGroups: NamedMediaGroup[]) {\n if (mediaType !== MediaType.AudioMain) {\n throw new Error(\n `sendSlotManager cannot set named media group which media type is ${mediaType}`\n );\n }\n\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n slot.setNamedMediaGroups(namedMediaGroups);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->setNamedMediaGroups#set named media group ${namedMediaGroups}`\n );\n }\n\n /**\n * This method publishes the given stream to the sendSlot for the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot to which a stream needs to be published (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {LocalStream} stream LocalStream to be published\n * @returns {Promise<void>}\n */\n public async publishStream(mediaType: MediaType, stream: LocalStream): Promise<void> {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.publishStream(stream);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->publishStream#Published stream for ${mediaType} and stream with label ${stream.label} and muted ${stream.muted}`\n );\n }\n\n /**\n * This method unpublishes the stream from the sendSlot of the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot from which a stream needs to be unpublished (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @returns {Promise<void>}\n */\n public async unpublishStream(mediaType: MediaType): Promise<void> {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.unpublishStream();\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->unpublishStream#Unpublished stream for ${mediaType}`\n );\n }\n\n /**\n * This method is used to set the active state of the sendSlot for the given mediaType\n * @param {MediaType} mediaType The MediaType of the sendSlot for which the active state needs to be set (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {boolean} active The boolean to set the active state of the sendSlot. Default is true\n * @returns {void}\n */\n public setActive(mediaType: MediaType, active = true): void {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n slot.active = active;\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->setActive#Set active for ${mediaType} to ${active}`\n );\n }\n\n /**\n * This method is used to set the codec parameters for the sendSlot of the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot for which the codec parameters needs to be set (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {Object} codecParameters\n * @returns {Promise<void>}\n */\n public async setCodecParameters(\n mediaType: MediaType,\n codecParameters: {\n [key: string]: string | undefined; // As per ts-sdp undefined is considered as a valid value to be used for codec parameters\n }\n ): Promise<void> {\n // These codec parameter changes underneath are SDP value changes that are taken care by WCME automatically. So no need for any change in streams from the web sdk side\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.setCodecParameters(codecParameters);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->setCodecParameters#Set codec parameters for ${mediaType} to ${codecParameters}`\n );\n }\n\n /**\n * This method is used to delete the codec parameters for the sendSlot of the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot for which the codec parameters needs to be deleted (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {Array<String>} parameters Array of keys of the codec parameters to be deleted\n * @returns {Promise<void>}\n */\n public async deleteCodecParameters(mediaType: MediaType, parameters: string[]): Promise<void> {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.deleteCodecParameters(parameters);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->deleteCodecParameters#Deleted the following codec parameters -> ${parameters} for ${mediaType}`\n );\n }\n\n /**\n * This method is used to reset the SendSlotsManager by deleting all the sendSlots\n * @returns {undefined}\n */\n public reset(): void {\n this.slots.clear();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAKoC,IAIfA,eAAe;EAIlC,yBAAYC,WAAgB,EAAE;IAAA;IAAA,6CAHqB,kBAAS;IAAA;IAI1D,IAAI,CAACA,WAAW,GAAGA,WAAW;EAChC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,oBACEC,eAA+C,EAC/CC,SAAoB,EAEV;MAAA,IADVC,MAAM,uEAAG,IAAI;MAEb,IAAI,IAAI,CAACC,KAAK,CAACC,GAAG,CAACH,SAAS,CAAC,EAAE;QAC7B,MAAM,IAAII,KAAK,oBAAaJ,SAAS,qBAAkB;MACzD;MAEA,IAAMK,IAAc,GAAGN,eAAe,CAACO,cAAc,CAACN,SAAS,EAAEC,MAAM,CAAC;MAExE,IAAI,CAACC,KAAK,CAACK,GAAG,CAACP,SAAS,EAAEK,IAAI,CAAC;MAE/B,IAAI,CAACP,WAAW,CAACU,MAAM,CAACC,IAAI,yDACuBT,SAAS,0BAAgBC,MAAM,EACjF;MAED,OAAOI,IAAI;IACb;;IAEA;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA,OAKA,iBAAeL,SAAoB,EAAY;MAC7C,IAAMK,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;MAEtC,IAAI,CAACK,IAAI,EAAE;QACT,MAAM,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;MACzD;MAEA,OAAOK,IAAI;IACb;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,6BAA2BL,SAAoB,EAAEW,gBAAmC,EAAE;MACpF,IAAIX,SAAS,KAAKY,4BAAS,CAACC,SAAS,EAAE;QACrC,MAAM,IAAIT,KAAK,4EACuDJ,SAAS,EAC9E;MACH;MAEA,IAAMK,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;MAEtC,IAAI,CAACK,IAAI,EAAE;QACT,MAAM,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;MACzD;MAEAK,IAAI,CAACS,mBAAmB,CAACH,gBAAgB,CAAC;MAE1C,IAAI,CAACb,WAAW,CAACU,MAAM,CAACC,IAAI,uEACqCE,gBAAgB,EAChF;IACH;;IAEA;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA;MAAA,6FAMA,iBAA2BX,SAAoB,EAAEe,MAAmB;QAAA;QAAA;UAAA;YAAA;cAC5DV,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;cAAA,IAEjCK,IAAI;gBAAA;gBAAA;cAAA;cAAA,MACD,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;YAAA;cAAA;cAAA,OAGnDK,IAAI,CAACW,aAAa,CAACD,MAAM,CAAC;YAAA;cAEhC,IAAI,CAACjB,WAAW,CAACU,MAAM,CAACC,IAAI,gEAC8BT,SAAS,oCAA0Be,MAAM,CAACE,KAAK,wBAAcF,MAAM,CAACG,KAAK,EAClI;YAAC;YAAA;cAAA;UAAA;QAAA;MAAA,CACH;MAAA;QAAA;MAAA;MAAA;IAAA;IAED;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA;MAAA,+FAKA,kBAA6BlB,SAAoB;QAAA;QAAA;UAAA;YAAA;cACzCK,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;cAAA,IAEjCK,IAAI;gBAAA;gBAAA;cAAA;cAAA,MACD,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;YAAA;cAAA;cAAA,OAGnDK,IAAI,CAACc,eAAe,EAAE;YAAA;cAE5B,IAAI,CAACrB,WAAW,CAACU,MAAM,CAACC,IAAI,oEACkCT,SAAS,EACtE;YAAC;YAAA;cAAA;UAAA;QAAA;MAAA,CACH;MAAA;QAAA;MAAA;MAAA;IAAA;IAED;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA,OAMA,mBAAiBA,SAAoB,EAAuB;MAAA,IAArBC,MAAM,uEAAG,IAAI;MAClD,IAAMI,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;MAEtC,IAAI,CAACK,IAAI,EAAE;QACT,MAAM,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;MACzD;MAEAK,IAAI,CAACJ,MAAM,GAAGA,MAAM;MAEpB,IAAI,CAACH,WAAW,CAACU,MAAM,CAACC,IAAI,sDACoBT,SAAS,iBAAOC,MAAM,EACrE;IACH;;IAEA;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA;MAAA,kGAMA,kBACED,SAAoB,EACpBoB,eAEC;QAAA;QAAA;UAAA;YAAA;cAED;cACMf,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;cAAA,IAEjCK,IAAI;gBAAA;gBAAA;cAAA;cAAA,MACD,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;YAAA;cAAA;cAAA,OAGnDK,IAAI,CAACgB,kBAAkB,CAACD,eAAe,CAAC;YAAA;cAE9C,IAAI,CAACtB,WAAW,CAACU,MAAM,CAACC,IAAI,yEACuCT,SAAS,iBAAOoB,eAAe,EACjG;YAAC;YAAA;cAAA;UAAA;QAAA;MAAA,CACH;MAAA;QAAA;MAAA;MAAA;IAAA;IAED;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA;MAAA,qGAMA,kBAAmCpB,SAAoB,EAAEsB,UAAoB;QAAA;QAAA;UAAA;YAAA;cACrEjB,IAAI,GAAG,IAAI,CAACH,KAAK,CAACQ,GAAG,CAACV,SAAS,CAAC;cAAA,IAEjCK,IAAI;gBAAA;gBAAA;cAAA;cAAA,MACD,IAAID,KAAK,oBAAaJ,SAAS,qBAAkB;YAAA;cAAA;cAAA,OAGnDK,IAAI,CAACkB,qBAAqB,CAACD,UAAU,CAAC;YAAA;cAE5C,IAAI,CAACxB,WAAW,CAACU,MAAM,CAACC,IAAI,6FAC2Da,UAAU,kBAAQtB,SAAS,EACjH;YAAC;YAAA;cAAA;UAAA;QAAA;MAAA,CACH;MAAA;QAAA;MAAA;MAAA;IAAA;IAED;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,iBAAqB;MACnB,IAAI,CAACE,KAAK,CAACsB,KAAK,EAAE;IACpB;EAAC;EAAA;AAAA;AAAA"}
|
|
1
|
+
{"version":3,"names":["SendSlotManager","LoggerProxy","mediaConnection","mediaType","active","slots","has","Error","slot","createSendSlot","set","logger","info","get","namedMediaGroups","MediaType","AudioMain","setNamedMediaGroups","stream","publishStream","label","muted","unpublishStream","codecParameters","setCodecParameters","parameters","deleteCodecParameters","clear"],"sources":["sendSlotManager.ts"],"sourcesContent":["import {\n SendSlot,\n MediaType,\n LocalStream,\n MultistreamRoapMediaConnection,\n NamedMediaGroup,\n} from '@webex/internal-media-core';\n\nexport default class SendSlotManager {\n private readonly slots: Map<MediaType, SendSlot> = new Map();\n private readonly LoggerProxy: any;\n\n constructor(LoggerProxy: any) {\n this.LoggerProxy = LoggerProxy;\n }\n\n /**\n * This method is used to create a sendSlot for the given mediaType and returns the created sendSlot\n * @param {MultistreamRoapMediaConnection} mediaConnection MultistreamRoapMediaConnection for which a sendSlot needs to be created\n * @param {MediaType} mediaType MediaType for which a sendSlot needs to be created (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {boolean} active This is optional boolean to set the active state of the sendSlot. Default is true\n * @returns {SendSlot} slot The created sendSlot\n */\n public createSlot(\n mediaConnection: MultistreamRoapMediaConnection,\n mediaType: MediaType,\n active = true\n ): SendSlot {\n if (this.slots.has(mediaType)) {\n throw new Error(`Slot for ${mediaType} already exists`);\n }\n\n const slot: SendSlot = mediaConnection.createSendSlot(mediaType, active);\n\n this.slots.set(mediaType, slot);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->createSlot#Created slot for ${mediaType} with active ${active}`\n );\n\n return slot;\n }\n\n /**\n * This method is used to retrieve the sendSlot for the given mediaType\n * @param {MediaType} mediaType of which the slot needs to be retrieved\n * @returns {SendSlot}\n */\n public getSlot(mediaType: MediaType): SendSlot {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n return slot;\n }\n\n /**\n * Allow users to specify 'namedMediaGroups' to indicate which named media group its audio should be sent to.\n * @param {MediaType} mediaType MediaType of the sendSlot to which the audio stream needs to be send to the media group\n * @param {[]}namedMediaGroups - Allow users to specify 'namedMediaGroups'.If the value of 'namedMediaGroups' is zero,\n * named media group will be canceled and the audio stream will be sent to the floor.\n * @returns {void}\n */\n public setNamedMediaGroups(mediaType: MediaType, namedMediaGroups: NamedMediaGroup[]) {\n if (mediaType !== MediaType.AudioMain) {\n throw new Error(\n `sendSlotManager cannot set named media group which media type is ${mediaType}`\n );\n }\n\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n slot.setNamedMediaGroups(namedMediaGroups);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->setNamedMediaGroups#set named media group ${namedMediaGroups}`\n );\n }\n\n /**\n * This method publishes the given stream to the sendSlot for the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot to which a stream needs to be published (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {LocalStream} stream LocalStream to be published\n * @returns {Promise<void>}\n */\n public async publishStream(mediaType: MediaType, stream: LocalStream): Promise<void> {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.publishStream(stream);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->publishStream#Published stream for ${mediaType} and stream with label ${stream.label} and muted ${stream.muted}`\n );\n }\n\n /**\n * This method unpublishes the stream from the sendSlot of the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot from which a stream needs to be unpublished (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @returns {Promise<void>}\n */\n public async unpublishStream(mediaType: MediaType): Promise<void> {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.unpublishStream();\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->unpublishStream#Unpublished stream for ${mediaType}`\n );\n }\n\n /**\n * This method is used to set the active state of the sendSlot for the given mediaType\n * @param {MediaType} mediaType The MediaType of the sendSlot for which the active state needs to be set (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {boolean} active The boolean to set the active state of the sendSlot. Default is true\n * @returns {void}\n */\n public setActive(mediaType: MediaType, active = true): void {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n slot.active = active;\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->setActive#Set active for ${mediaType} to ${active}`\n );\n }\n\n /**\n * This method is used to set the codec parameters for the sendSlot of the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot for which the codec parameters needs to be set (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {Object} codecParameters\n * @returns {Promise<void>}\n */\n public async setCodecParameters(\n mediaType: MediaType,\n codecParameters: {\n [key: string]: string | undefined; // As per ts-sdp undefined is considered as a valid value to be used for codec parameters\n }\n ): Promise<void> {\n // These codec parameter changes underneath are SDP value changes that are taken care by WCME automatically. So no need for any change in streams from the web sdk side\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.setCodecParameters(codecParameters);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->setCodecParameters#Set codec parameters for ${mediaType} to ${codecParameters}`\n );\n }\n\n /**\n * This method is used to delete the codec parameters for the sendSlot of the given mediaType\n * @param {MediaType} mediaType MediaType of the sendSlot for which the codec parameters needs to be deleted (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)\n * @param {Array<String>} parameters Array of keys of the codec parameters to be deleted\n * @returns {Promise<void>}\n */\n public async deleteCodecParameters(mediaType: MediaType, parameters: string[]): Promise<void> {\n const slot = this.slots.get(mediaType);\n\n if (!slot) {\n throw new Error(`Slot for ${mediaType} does not exist`);\n }\n\n await slot.deleteCodecParameters(parameters);\n\n this.LoggerProxy.logger.info(\n `SendSlotsManager->deleteCodecParameters#Deleted the following codec parameters -> ${parameters} for ${mediaType}`\n );\n }\n\n /**\n * This method is used to reset the SendSlotsManager by deleting all the sendSlots\n * @returns {undefined}\n */\n public reset(): void {\n this.slots.clear();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { StreamRequest } from '@webex/internal-media-core';
|
|
2
|
-
import { NamedMediaGroup } from '@webex/json-multistream';
|
|
1
|
+
import { StreamRequest, NamedMediaGroup } from '@webex/internal-media-core';
|
|
3
2
|
import { ReceiveSlot } from './receiveSlot';
|
|
4
3
|
export interface ActiveSpeakerPolicyInfo {
|
|
5
4
|
policy: 'active-speaker';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NamedMediaGroup } from '@webex/
|
|
1
|
+
import { NamedMediaGroup } from '@webex/internal-media-core';
|
|
2
2
|
import { RemoteMedia, RemoteVideoResolution } from './remoteMedia';
|
|
3
3
|
import { MediaRequestManager } from './mediaRequestManager';
|
|
4
4
|
import { CSI, ReceiveSlot } from './receiveSlot';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { EventMap } from 'typed-emitter';
|
|
2
|
-
import { MediaType } from '@webex/internal-media-core';
|
|
3
|
-
import { NamedMediaGroup } from '@webex/json-multistream';
|
|
2
|
+
import { MediaType, NamedMediaGroup } from '@webex/internal-media-core';
|
|
4
3
|
import EventsScope from '../common/events/events-scope';
|
|
5
4
|
import { RemoteMedia, RemoteVideoResolution } from './remoteMedia';
|
|
6
5
|
import { CSI } from './receiveSlot';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { SendSlot, MediaType, LocalStream, MultistreamRoapMediaConnection } from '@webex/internal-media-core';
|
|
2
|
-
import { NamedMediaGroup } from '@webex/json-multistream';
|
|
1
|
+
import { SendSlot, MediaType, LocalStream, MultistreamRoapMediaConnection, NamedMediaGroup } from '@webex/internal-media-core';
|
|
3
2
|
export default class SendSlotManager {
|
|
4
3
|
private readonly slots;
|
|
5
4
|
private readonly LoggerProxy;
|
package/dist/webinar/index.js
CHANGED
|
@@ -62,7 +62,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
|
|
|
62
62
|
updateCanManageWebcast: function updateCanManageWebcast(canManageWebcast) {
|
|
63
63
|
this.set('canManageWebcast', canManageWebcast);
|
|
64
64
|
},
|
|
65
|
-
version: "3.0.0-beta.
|
|
65
|
+
version: "3.0.0-beta.404"
|
|
66
66
|
});
|
|
67
67
|
var _default = Webinar;
|
|
68
68
|
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.404",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@peculiar/webcrypto": "^1.4.3",
|
|
36
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
41
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
36
|
+
"@webex/plugin-meetings": "3.0.0-beta.404",
|
|
37
|
+
"@webex/test-helper-chai": "3.0.0-beta.404",
|
|
38
|
+
"@webex/test-helper-mocha": "3.0.0-beta.404",
|
|
39
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.404",
|
|
40
|
+
"@webex/test-helper-retry": "3.0.0-beta.404",
|
|
41
|
+
"@webex/test-helper-test-users": "3.0.0-beta.404",
|
|
42
42
|
"chai": "^4.3.4",
|
|
43
43
|
"chai-as-promised": "^7.1.1",
|
|
44
44
|
"jsdom-global": "3.0.2",
|
|
@@ -47,19 +47,19 @@
|
|
|
47
47
|
"typescript": "^4.7.4"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@webex/common": "3.0.0-beta.
|
|
51
|
-
"@webex/internal-media-core": "2.3.
|
|
52
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
58
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
59
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
61
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
62
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
50
|
+
"@webex/common": "3.0.0-beta.404",
|
|
51
|
+
"@webex/internal-media-core": "2.3.2",
|
|
52
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.404",
|
|
53
|
+
"@webex/internal-plugin-device": "3.0.0-beta.404",
|
|
54
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.404",
|
|
55
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.404",
|
|
56
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.404",
|
|
57
|
+
"@webex/internal-plugin-support": "3.0.0-beta.404",
|
|
58
|
+
"@webex/internal-plugin-user": "3.0.0-beta.404",
|
|
59
|
+
"@webex/media-helpers": "3.0.0-beta.404",
|
|
60
|
+
"@webex/plugin-people": "3.0.0-beta.404",
|
|
61
|
+
"@webex/plugin-rooms": "3.0.0-beta.404",
|
|
62
|
+
"@webex/webex-core": "3.0.0-beta.404",
|
|
63
63
|
"ampersand-collection": "^2.0.2",
|
|
64
64
|
"bowser": "^2.11.0",
|
|
65
65
|
"btoa": "^1.2.1",
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
H264Codec,
|
|
9
9
|
getRecommendedMaxBitrateForFrameSize,
|
|
10
10
|
RecommendedOpusBitrates,
|
|
11
|
+
NamedMediaGroup,
|
|
11
12
|
} from '@webex/internal-media-core';
|
|
12
13
|
import {cloneDeepWith, debounce, isEmpty} from 'lodash';
|
|
13
14
|
|
|
14
|
-
import {NamedMediaGroup} from '@webex/json-multistream';
|
|
15
15
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
16
16
|
|
|
17
17
|
import {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable require-jsdoc */
|
|
3
3
|
/* eslint-disable import/prefer-default-export */
|
|
4
4
|
import {forEach} from 'lodash';
|
|
5
|
-
import {NamedMediaGroup} from '@webex/
|
|
5
|
+
import {NamedMediaGroup} from '@webex/internal-media-core';
|
|
6
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
7
|
|
|
8
8
|
import {getMaxFs, RemoteMedia, RemoteVideoResolution} from './remoteMedia';
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* eslint-disable valid-jsdoc */
|
|
2
2
|
import {cloneDeep, forEach, remove} from 'lodash';
|
|
3
3
|
import {EventMap} from 'typed-emitter';
|
|
4
|
-
import {MediaType} from '@webex/internal-media-core';
|
|
5
|
-
import {NamedMediaGroup} from '@webex/json-multistream';
|
|
4
|
+
import {MediaType, NamedMediaGroup} from '@webex/internal-media-core';
|
|
6
5
|
|
|
7
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
8
7
|
import EventsScope from '../common/events/events-scope';
|
|
@@ -3,10 +3,9 @@ import {
|
|
|
3
3
|
MediaType,
|
|
4
4
|
LocalStream,
|
|
5
5
|
MultistreamRoapMediaConnection,
|
|
6
|
+
NamedMediaGroup,
|
|
6
7
|
} from '@webex/internal-media-core';
|
|
7
8
|
|
|
8
|
-
import {NamedMediaGroup} from '@webex/json-multistream';
|
|
9
|
-
|
|
10
9
|
export default class SendSlotManager {
|
|
11
10
|
private readonly slots: Map<MediaType, SendSlot> = new Map();
|
|
12
11
|
private readonly LoggerProxy: any;
|
|
@@ -6,7 +6,6 @@ import {RemoteMedia} from '@webex/plugin-meetings/src/multistream/remoteMedia';
|
|
|
6
6
|
import {ReceiveSlot} from '@webex/plugin-meetings/src/multistream/receiveSlot';
|
|
7
7
|
import sinon from 'sinon';
|
|
8
8
|
import {assert} from '@webex/test-helper-chai';
|
|
9
|
-
import { NamedMediaGroup } from "@webex/json-multistream";
|
|
10
9
|
|
|
11
10
|
class FakeSlot extends EventEmitter {
|
|
12
11
|
public mediaType: MediaType;
|
|
@@ -18,7 +18,6 @@ import testUtils from '../../../utils/testUtils';
|
|
|
18
18
|
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
19
19
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
20
20
|
import { expect } from 'chai';
|
|
21
|
-
import { NamedMediaGroup } from "@webex/json-multistream";
|
|
22
21
|
|
|
23
22
|
class FakeSlot extends EventEmitter {
|
|
24
23
|
public mediaType: MediaType;
|