private updateRemoteVideosFromLastVideosToReceive()

in src/audiovideocontroller/DefaultAudioVideoController.ts [828:923]


  private updateRemoteVideosFromLastVideosToReceive(): boolean {
    const context = this.meetingSessionContext;
    if (context.videosToReceive?.empty() || context.lastVideosToReceive?.empty()) {
      return false;
    }

    // Check existence of all required dependencies and requisite functions
    if (
      !context.transceiverController ||
      !context.transceiverController.getMidForStreamId ||
      !context.transceiverController.setStreamIdForMid ||
      !context.videosToReceive.forEach ||
      !context.signalingClient.remoteVideoUpdate ||
      !context.videoStreamIndex.overrideStreamIdMappings
    ) {
      return false;
    }

    let added: number[] = [];
    const simulcastStreamUpdates: Map<number, number> = new Map();
    let removed: number[] = [];

    if (context.lastVideosToReceive === null) {
      added = context.videosToReceive.array();
    } else {
      const index = context.videoStreamIndex;
      context.videosToReceive.forEach((currentId: number) => {
        if (context.lastVideosToReceive.contain(currentId)) {
          return;
        }

        // Check if group ID exists in previous set (i.e. simulcast stream switch)
        let foundUpdatedPreviousStreamId = false;
        context.lastVideosToReceive.forEach((previousId: number) => {
          if (foundUpdatedPreviousStreamId) {
            return; // Short circuit since we have already found it
          }
          if (index.StreamIdsInSameGroup(previousId, currentId)) {
            simulcastStreamUpdates.set(previousId, currentId);
            foundUpdatedPreviousStreamId = true;
          }
        });
        if (!foundUpdatedPreviousStreamId) {
          // Otherwise this must be a new stream
          added.push(currentId);
        }
      });
      removed = context.lastVideosToReceive.array().filter(idFromPrevious => {
        const stillReceiving = context.videosToReceive.contain(idFromPrevious);
        const isUpdated = simulcastStreamUpdates.has(idFromPrevious);
        return !stillReceiving && !isUpdated;
      });
    }
    this.logger.info(
      `Request to update remote videos with added: ${added}, updated: ${[
        ...simulcastStreamUpdates.entries(),
      ]}, removed: ${removed}`
    );

    const updatedVideoSubscriptionConfigurations: SignalingClientVideoSubscriptionConfiguration[] = [];
    for (const [previousId, currentId] of simulcastStreamUpdates.entries()) {
      const updatedConfig = new SignalingClientVideoSubscriptionConfiguration();
      updatedConfig.streamId = currentId;
      updatedConfig.attendeeId = context.videoStreamIndex.attendeeIdForStreamId(currentId);
      updatedConfig.mid = context.transceiverController.getMidForStreamId(previousId);
      if (updatedConfig.mid === undefined) {
        this.logger.info(
          `No MID found for stream ID ${previousId}, cannot update stream without renegotiation`
        );
        return false;
      }
      updatedVideoSubscriptionConfigurations.push(updatedConfig);
      // We need to override some other components dependent on the subscribe paths for certain functionality
      context.transceiverController.setStreamIdForMid(updatedConfig.mid, currentId);
      context.videoStreamIndex.overrideStreamIdMappings(previousId, currentId);
      if (context.videoTileController.haveVideoTileForAttendeeId(updatedConfig.attendeeId)) {
        const tile = context.videoTileController.getVideoTileForAttendeeId(
          updatedConfig.attendeeId
        );
        if (!tile.setStreamId) {
          // Required function
          return false;
        }
        tile.setStreamId(currentId);
      }
    }
    if (updatedVideoSubscriptionConfigurations.length !== 0) {
      context.signalingClient.remoteVideoUpdate(updatedVideoSubscriptionConfigurations, []);
    }

    // Only simulcast stream switches (i.e. not add/remove/source switches) are possible currently
    if (added.length !== 0 || removed.length !== 0) {
      return false;
    }
    return true;
  }