private updateTransceivers()

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`
      );
    }
  }