import { ReceiverEstimatedMaxBitrate , RtcpPacket , RtcpPayloadSpecificFeedback , RtcpRrPacket , RtcpSourceDescriptionPacket , RtcpSrPacket , RtcpTransportLayerFeedback , RtpPacket , } from "../../../rtp/src" ; import { RTP_EXTENSION_URI } from "../extension/rtpExtension" ; import { RTCRtpReceiveParameters , RTCRtpSimulcastParameters , } from "./parameters" ; import { RTCRtpReceiver } from "./rtpReceiver" ; import { RTCRtpSender } from "./rtpSender" ; import { RTCRtpTransceiver } from "./rtpTransceiver" ; import { RtpTrack } from "./track" ; export type Extensions = { [ uri ] : number | string ; } ; export class RtpRouter { ssrcTable : { [ ssrc ] : RTCRtpReceiver | RTCRtpSender ; } = { } ; ridTable : { [ rid ] : RTCRtpReceiver | RTCRtpSender ; } = { } ; extIdUriMap : { [ id ] : string ; } = { } ; registerRtpReceiverBySsrc ( transceiver , params ) { const ssrcs = params . encodings . map ( ( encode ) => encode . ssrc ) . filter ( ( v ) => v ) ; ssrcs . forEach ( ( ssrc ) => { this . ssrcTable [ ssrc ] = transceiver . receiver ; transceiver . addTrack ( new RtpTrack ( { ssrc , kind : transceiver . kind , id : transceiver . sender . streamId , } ) ) ; } ) ; params . headerExtensions . forEach ( ( extension ) => { this . extIdUriMap [ extension . id ] = extension . uri ; } ) ; } registerRtpReceiverByRid ( transceiver , param ) { transceiver . addTrack ( new RtpTrack ( { rid : param . rid , kind : transceiver . kind , id : transceiver . sender . streamId , } ) ) ; this . ridTable [ param . rid ] = transceiver . receiver ; } routeRtp = ( packet ) => { const extensions = packet . header . extensions . map ( ( extension ) => { const uri = this . extIdUriMap [ extension . id ] ; switch ( uri ) { case RTP_EXTENSION_URI . sdesMid : case RTP_EXTENSION_URI . sdesRTPStreamID : return { uri , value : extension . payload . toString ( ) } ; case RTP_EXTENSION_URI . transportWideCC : return { uri , value : extension . payload . readUInt16BE ( ) } ; case RTP_EXTENSION_URI . absSendTime : return { uri , value : extension . payload . readUIntBE ( 0 , 3 ) } ; } } ) . reduce ( ( acc , cur ) => { if ( cur ) acc [ cur . uri ] = cur . value ; return acc ; } , { } as { [ uri ] : any ; } ) ; let ssrcReceiver = this . ssrcTable [ packet . header . ssrc ] as RTCRtpReceiver ; const rid = extensions [ RTP_EXTENSION_URI . sdesRTPStreamID ] as string ; if ( rid ) { ssrcReceiver = this . ridTable [ rid ] as RTCRtpReceiver ; ssrcReceiver . handleRtpByRid ( packet , rid , extensions ) ; } else { if ( ! ssrcReceiver ) return ; ssrcReceiver . handleRtpBySsrc ( packet , extensions ) ; } ssrcReceiver . sdesMid = extensions [ "urn:ietf:params:rtp-hdrext:sdes:mid" ] as string ; } ; routeRtcp = ( packet ) => { const recipients = [ ] ; switch ( packet . type ) { case RtcpSrPacket . type : { packet = packet as RtcpSrPacket ; recipients . push ( this . ssrcTable [ packet . ssrc ] ) ; } break ; case RtcpRrPacket . type : { packet = packet as RtcpRrPacket ; packet . reports . forEach ( ( report ) => { recipients . push ( this . ssrcTable [ report . ssrc ] ) ; } ) ; } break ; case RtcpSourceDescriptionPacket . type : { const sdes = packet as RtcpSourceDescriptionPacket ; } break ; case RtcpTransportLayerFeedback . type : { const rtpfb = packet as RtcpTransportLayerFeedback ; if ( rtpfb . feedback ) { recipients . push ( this . ssrcTable [ rtpfb . feedback . mediaSsrc ] ) ; } } break ; case RtcpPayloadSpecificFeedback . type : { const psfb = packet as RtcpPayloadSpecificFeedback ; switch ( psfb . feedback . count ) { case ReceiverEstimatedMaxBitrate . count : const remb = psfb . feedback as ReceiverEstimatedMaxBitrate ; recipients . push ( this . ssrcTable [ remb . ssrcFeedbacks [ 0 ] ] ) ; break ; default : recipients . push ( this . ssrcTable [ psfb . feedback . senderSsrc ] ) ; } } break ; } recipients . filter ( ( v ) => v ) . forEach ( ( recipient ) => recipient . handleRtcpPacket ( packet ) ) ; } ; }