in src/transceivercontroller/DefaultTransceiverController.ts [214:292]
private updateTransceivers(
transceivers: RTCRtpTransceiver[],
videoStreamIndex: VideoStreamIndex,
videosToReceive: VideoStreamIdSet
): void {
const videosRemaining = videosToReceive.array();
// Start by handling existing videos
// Begin counting out index in the the subscription array at 1 since the camera.
// Always occupies position 0 (whether active or not).
let n = 1;
for (const transceiver of transceivers) {
if (transceiver === this._localCameraTransceiver || !this.transceiverIsVideo(transceiver)) {
continue;
}
this.videoSubscriptions[n] = 0;
if (transceiver.direction !== 'inactive') {
// See if we want this existing transceiver
// by convention with the video host, msid is equal to the media section mid, prefixed with the string "v_"
// we use this to get the streamId for the track
const streamId = videoStreamIndex.streamIdForTrack('v_' + transceiver.mid);
if (streamId !== undefined) {
for (const [index, recvStreamId] of videosRemaining.entries()) {
if (videoStreamIndex.StreamIdsInSameGroup(streamId, recvStreamId)) {
transceiver.direction = 'recvonly';
this.videoSubscriptions[n] = recvStreamId;
this.streamIdToTransceiver.delete(streamId);
this.streamIdToTransceiver.set(recvStreamId, transceiver);
videosRemaining.splice(index, 1);
break;
}
}
}
}
n += 1;
}
// Next fill in open slots and remove unused
n = 1;
for (const transceiver of transceivers) {
if (transceiver === this._localCameraTransceiver || !this.transceiverIsVideo(transceiver)) {
continue;
}
if (transceiver.direction === 'inactive' && videosRemaining.length > 0) {
// Fill available slot
transceiver.direction = 'recvonly';
const streamId = videosRemaining.shift();
this.videoSubscriptions[n] = streamId;
this.streamIdToTransceiver.set(streamId, transceiver);
} else {
// Remove if no longer subscribed
if (this.videoSubscriptions[n] === 0) {
transceiver.direction = 'inactive';
for (const [streamId, previousTransceiver] of this.streamIdToTransceiver.entries()) {
if (transceiver === previousTransceiver) {
this.streamIdToTransceiver.delete(streamId);
}
}
}
}
n += 1;
}
// add transceivers for the remaining subscriptions
for (const index of videosRemaining) {
// @ts-ignore
const transceiver = this.peer.addTransceiver('video', {
direction: 'recvonly',
streams: [this.defaultMediaStream],
});
this.streamIdToTransceiver.set(index, transceiver);
this.videoSubscriptions.push(index);
this.logger.info(
`adding transceiver mid: ${transceiver.mid} subscription: ${index} direction: recvonly`
);
}
}