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