private updateTransceiverWithStop()

in src/transceivercontroller/DefaultTransceiverController.ts [258:320]


  private updateTransceiverWithStop(
    transceivers: RTCRtpTransceiver[],
    videoStreamIndex: VideoStreamIndex,
    videosRemaining: number[]
  ): void {
    // 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;
    // Reset since otherwise there will be stale indexes corresponding to
    // stopped transceivers.
    this.videoSubscriptions = [0];

    for (const transceiver of transceivers) {
      if (
        transceiver === this._localCameraTransceiver ||
        !this.transceiverIsVideo(transceiver) ||
        !transceiver.mid
      ) {
        continue;
      }

      let reusingTranceiver = false;
      // See if we want this existing transceiver for a simulcast stream switch
      //
      // By convention with the service backend, msid is equal to the media section mid, prefixed with the string "v_";
      // we use this to get the stream ID for the track
      const streamId = videoStreamIndex.streamIdForTrack('v_' + transceiver.mid);
      if (transceiver.direction !== 'inactive' && streamId !== undefined) {
        for (const [index, recvStreamId] of videosRemaining.entries()) {
          // `streamId` may still be the same as `recvStreamId`
          if (videoStreamIndex.StreamIdsInSameGroup(streamId, recvStreamId)) {
            transceiver.direction = 'recvonly';
            this.videoSubscriptions[n] = recvStreamId;
            reusingTranceiver = true;

            this.streamIdToTransceiver.delete(streamId);
            this.streamIdToTransceiver.set(recvStreamId, transceiver);
            videosRemaining.splice(index, 1);
            break;
          }
        }
      }

      if (!reusingTranceiver) {
        this.videoSubscriptions[n] = 0;
        this.logger.info(
          `Stopping MID: ${transceiver.mid}, direction: ${transceiver.direction}, current direction: ${transceiver.currentDirection}`
        );
        // Clean up transceiver and mappings for streams that have been unsubscribed from.  Note we do not try to reuse
        // old inactive transceivers for new streams as Firefox will reuse the last frame from
        // that transceiver, and additionally we simply don't want to risk wiring up a transceiver
        // to the incorrect video stream for no real benefit besides possible a smaller SDP size.
        transceiver.stop(); // Note (as of Firefox 94): Firefox will keep these around forever
        for (const [streamId, previousTransceiver] of this.streamIdToTransceiver.entries()) {
          if (transceiver.mid === previousTransceiver.mid) {
            this.streamIdToTransceiver.delete(streamId);
            this.groupIdToTransceiver.delete(videoStreamIndex.groupIdForStreamId(streamId));
          }
        }
      }
      n += 1;
    }
  }