From 24bb7a9f68f1eff48ca41c88a598890a324cb856 Mon Sep 17 00:00:00 2001 From: cnderrauber Date: Thu, 24 Oct 2024 21:49:55 +0800 Subject: [PATCH] Keep dd extension id in the session (#1297) * Keep dd extension id in the session Safari could generate different rtp extensions for video tracks(camera and screenshare), need to use same extension id for dependency descriptor in the offer. * changeset and prettier * parse entire offer for max extension id --- .changeset/young-steaks-switch.md | 5 +++ src/room/PCTransport.ts | 71 ++++++++++++++++++------------- 2 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 .changeset/young-steaks-switch.md diff --git a/.changeset/young-steaks-switch.md b/.changeset/young-steaks-switch.md new file mode 100644 index 0000000000..f5f90bc64b --- /dev/null +++ b/.changeset/young-steaks-switch.md @@ -0,0 +1,5 @@ +--- +'livekit-client': patch +--- + +Keep dd extension id in the session diff --git a/src/room/PCTransport.ts b/src/room/PCTransport.ts index 44cc959b85..9ce16d7705 100644 --- a/src/room/PCTransport.ts +++ b/src/room/PCTransport.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events'; -import type { MediaDescription } from 'sdp-transform'; +import type { MediaDescription, SessionDescription } from 'sdp-transform'; import { parse, write } from 'sdp-transform'; import { debounce } from 'ts-debounce'; import log, { LoggerNames, getLogger } from '../logger'; @@ -48,6 +48,8 @@ export default class PCTransport extends EventEmitter { private loggerOptions: LoggerOptions; + private ddExtID = 0; + pendingCandidates: RTCIceCandidateInit[] = []; restartingIce: boolean = false; @@ -288,7 +290,7 @@ export default class PCTransport extends EventEmitter { } if (isSVCCodec(trackbr.codec)) { - ensureVideoDDExtensionForSVC(media); + this.ensureVideoDDExtensionForSVC(media, sdpParsed); } // TODO: av1 slow starting issue already fixed in chrome 124, clean this after some versions @@ -503,6 +505,44 @@ export default class PCTransport extends EventEmitter { throw new NegotiationError(msg); } } + + private ensureVideoDDExtensionForSVC( + media: { + type: string; + port: number; + protocol: string; + payloads?: string | undefined; + } & MediaDescription, + sdp: SessionDescription, + ) { + const ddFound = media.ext?.some((ext): boolean => { + if (ext.uri === ddExtensionURI) { + return true; + } + return false; + }); + + if (!ddFound) { + if (this.ddExtID === 0) { + let maxID = 0; + sdp.media.forEach((m) => { + if (m.type !== 'video') { + return; + } + m.ext?.forEach((ext) => { + if (ext.value > maxID) { + maxID = ext.value; + } + }); + }); + this.ddExtID = maxID + 1; + } + media.ext?.push({ + value: this.ddExtID, + uri: ddExtensionURI, + }); + } + } } function ensureAudioNackAndStereo( @@ -555,33 +595,6 @@ function ensureAudioNackAndStereo( } } -function ensureVideoDDExtensionForSVC( - media: { - type: string; - port: number; - protocol: string; - payloads?: string | undefined; - } & MediaDescription, -) { - let maxID = 0; - const ddFound = media.ext?.some((ext): boolean => { - if (ext.uri === ddExtensionURI) { - return true; - } - if (ext.value > maxID) { - maxID = ext.value; - } - return false; - }); - - if (!ddFound) { - media.ext?.push({ - value: maxID + 1, - uri: ddExtensionURI, - }); - } -} - function extractStereoAndNackAudioFromOffer(offer: RTCSessionDescriptionInit): { stereoMids: string[]; nackMids: string[];