From a2ce73e0d0ab685c24f3d1e012cfac5dba1088a1 Mon Sep 17 00:00:00 2001 From: Raja Subramanian Date: Sat, 25 Oct 2025 14:30:30 +0530 Subject: [PATCH] Do not bind buffer if codec is invalid. (#4028) Seeing cases of codec with zero clock rate. Do not bind to those. --- pkg/rtc/mediatrack.go | 13 +++++++++++-- pkg/sfu/buffer/buffer.go | 20 ++++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/pkg/rtc/mediatrack.go b/pkg/rtc/mediatrack.go index f192d18c7..fb89c83c0 100644 --- a/pkg/rtc/mediatrack.go +++ b/pkg/rtc/mediatrack.go @@ -529,6 +529,17 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe if layer >= 0 && len(layers) > int(layer) { bitrates = int(layers[layer].GetBitrate()) } + if err := buff.Bind(receiver.GetParameters(), track.Codec().RTPCodecCapability, bitrates); err != nil { + t.params.Logger.Warnw( + "binding buffer failed", err, + "rid", track.RID(), + "layer", layer, + "ssrc", track.SSRC(), + "newCodec", newCodec, + ) + buff.Close() + return newCodec, false + } t.MediaTrackReceiver.SetLayerSsrc(mimeType, track.RID(), uint32(track.SSRC())) @@ -547,8 +558,6 @@ func (t *MediaTrack) AddReceiver(receiver *webrtc.RTPReceiver, track sfu.TrackRe } } - buff.Bind(receiver.GetParameters(), track.Codec().RTPCodecCapability, bitrates) - // if subscriber request fps before fps calculated, update them after fps updated. buff.OnFpsChanged(func() { t.MediaTrackSubscriptions.UpdateVideoLayers() diff --git a/pkg/sfu/buffer/buffer.go b/pkg/sfu/buffer/buffer.go index 72c32a6bc..02e6098fb 100644 --- a/pkg/sfu/buffer/buffer.go +++ b/pkg/sfu/buffer/buffer.go @@ -53,6 +53,10 @@ const ( InitPacketBufferSizeAudio = 70 ) +var ( + errInvalidCodec = errors.New("invalid codec") +) + type pendingPacket struct { arrivalTime int64 packet []byte @@ -214,11 +218,16 @@ func (b *Buffer) SetAudioLossProxying(enable bool) { b.enableAudioLossProxying = enable } -func (b *Buffer) Bind(params webrtc.RTPParameters, codec webrtc.RTPCodecCapability, bitrates int) { +func (b *Buffer) Bind(params webrtc.RTPParameters, codec webrtc.RTPCodecCapability, bitrates int) error { b.Lock() defer b.Unlock() if b.bound { - return + return nil + } + + if codec.ClockRate == 0 { + b.logger.Warnw("invalid codec", nil, "params", params, "codec", codec, "bitrates", bitrates) + return errInvalidCodec } b.rtpStats = rtpstats.NewRTPStatsReceiver(rtpstats.RTPStatsParams{ @@ -322,6 +331,8 @@ func (b *Buffer) Bind(params webrtc.RTPParameters, codec webrtc.RTPCodecCapabili if mime.IsMimeTypeVideo(b.mime) { go b.seedKeyFrame(b.keyFrameSeederGeneration.Inc()) } + + return nil } func (b *Buffer) OnCodecChange(fn func(webrtc.RTPCodecParameters)) { @@ -460,6 +471,11 @@ func (b *Buffer) writeRTX(rtxPkt *rtp.Packet, arrivalTime int64) (n int, err err b.rtxPktBuf = make([]byte, bucket.MaxPktSize) } + if len(rtxPkt.Payload) < 2 { + b.logger.Warnw("rtx payload too short", nil, "size", len(rtxPkt.Payload)) + return + } + repairedPkt := *rtxPkt repairedPkt.PayloadType = b.payloadType repairedPkt.SequenceNumber = binary.BigEndian.Uint16(rtxPkt.Payload[:2])