Do not restart receiver on codec change mid-session. (#4225)

* Do not restart receiver on codec change mid-session.

This is not supported and was an erroneous change during the
receiver_base/buffer_base + RTP stream restart consolidation. Also make
the codec munger creation more resilient.

* fix test
This commit is contained in:
Raja Subramanian
2026-01-08 02:35:32 +05:30
committed by GitHub
parent dafdc36e3e
commit 7fae5ac9e6
4 changed files with 17 additions and 12 deletions
-2
View File
@@ -964,8 +964,6 @@ func (b *BufferBase) handleCodecChange(newPT uint8) {
b.rtxPayloadType = rtxPt
b.mime = mime.NormalizeMimeType(newCodec.MimeType)
b.restartStreamLocked("codec-change", true)
if f := b.onCodecChange; f != nil {
go f(newCodec)
}
-6
View File
@@ -331,7 +331,6 @@ func TestCodecChange(t *testing.T) {
buff := NewBuffer(123, 1, 1)
require.NotNil(t, buff)
changedCodec := make(chan webrtc.RTPCodecParameters, 1)
restartCleared := make(chan struct{}, 1)
buff.OnCodecChange(func(rp webrtc.RTPCodecParameters) {
select {
case changedCodec <- rp:
@@ -347,8 +346,6 @@ func TestCodecChange(t *testing.T) {
extPkt, err := buff.ReadExtended(buf[:])
require.NoError(t, err)
require.Nil(t, extPkt)
restartCleared <- struct{}{}
})
h265Pkt := rtp.Packet{
@@ -391,7 +388,6 @@ func TestCodecChange(t *testing.T) {
case <-time.After(1 * time.Second):
t.Fatalf("expected codec change")
}
<-restartCleared
// second codec change - writing VP8 packet after Bind should trigger another codec change
vp8Pkt := rtp.Packet{
@@ -416,7 +412,6 @@ func TestCodecChange(t *testing.T) {
t.Fatalf("expected codec change")
}
fmt.Printf("done second codec change\n") // REMOVE
<-restartCleared
// out of order pkts can't cause codec change
// rewrite the VP8 packet to start the sequence after a stream restart
@@ -463,7 +458,6 @@ func TestCodecChange(t *testing.T) {
case <-time.After(1 * time.Second):
t.Fatalf("expected codec change")
}
<-restartCleared
}
func BenchmarkMemcpu(b *testing.B) {
+13 -3
View File
@@ -60,9 +60,14 @@ func NewVP8(logger logger.Logger) *VP8 {
}
}
func NewVP8FromNull(cm CodecMunger, logger logger.Logger) *VP8 {
func NewVP8FromOther(cm CodecMunger, logger logger.Logger) *VP8 {
v := NewVP8(logger)
v.SeedState(cm.(*Null).GetSeededState())
switch cm := cm.(type) {
case *Null:
v.SeedState(cm.GetSeededState())
case *VP8:
v.SeedState(cm.GetState())
}
return v
}
@@ -79,9 +84,14 @@ func (v *VP8) GetState() any {
}
func (v *VP8) SeedState(seed any) {
var state *livekit.VP8MungerState
switch cm := seed.(type) {
case *livekit.RTPForwarderState_Vp8Munger:
state := cm.Vp8Munger
state = cm.Vp8Munger
case *livekit.VP8MungerState:
state = cm
}
if state != nil {
v.extLastPictureId = state.ExtLastPictureId
v.pictureIdUsed = state.PictureIdUsed
v.lastTl0PicIdx = uint8(state.LastTl0PicIdx)
+4 -1
View File
@@ -334,7 +334,7 @@ func (f *Forwarder) DetermineCodec(codec webrtc.RTPCodecCapability, extensions [
switch f.mime {
case mime.MimeTypeVP8:
f.codecMunger = codecmunger.NewVP8FromNull(f.codecMunger, f.logger)
f.codecMunger = codecmunger.NewVP8FromOther(f.codecMunger, f.logger)
if f.vls != nil {
if vls := videolayerselector.NewSimulcastFromOther(f.vls); vls != nil {
f.vls = vls
@@ -347,6 +347,7 @@ func (f *Forwarder) DetermineCodec(codec webrtc.RTPCodecCapability, extensions [
f.vls.SetTemporalLayerSelector(temporallayerselector.NewVP8(f.logger))
case mime.MimeTypeH264, mime.MimeTypeH265:
f.codecMunger = codecmunger.NewNull(f.logger)
if f.vls != nil {
if vls := videolayerselector.NewSimulcastFromOther(f.vls); vls != nil {
f.vls = vls
@@ -358,6 +359,7 @@ func (f *Forwarder) DetermineCodec(codec webrtc.RTPCodecCapability, extensions [
}
case mime.MimeTypeVP9:
f.codecMunger = codecmunger.NewNull(f.logger)
if sfuutils.IsSimulcastMode(videoLayerMode) {
if f.vls != nil {
f.vls = videolayerselector.NewSimulcastFromOther(f.vls)
@@ -382,6 +384,7 @@ func (f *Forwarder) DetermineCodec(codec webrtc.RTPCodecCapability, extensions [
}
case mime.MimeTypeAV1:
f.codecMunger = codecmunger.NewNull(f.logger)
if sfuutils.IsSimulcastMode(videoLayerMode) {
if f.vls != nil {
f.vls = videolayerselector.NewSimulcastFromOther(f.vls)