Files
livekit/pkg/sfu/videolayerselector/framenumberwrapper.go
cnderrauber 5026de2bea handle frame number wrap back in svc (#3885)
* handle frame number wrap back in svc

* Add Slack Notifier

* check nil dd ext

* log format
2025-08-29 17:11:49 +08:00

59 lines
2.0 KiB
Go

// Copyright 2024 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package videolayerselector
import "github.com/livekit/protocol/logger"
type FrameNumberWrapper struct {
offset uint64
last uint64
inited bool
logger logger.Logger
}
// UpdateAndGet returns the wrapped frame number from the given frame number, and updates the offset to
// make sure the returned frame number is always inorder. Should only updateOffset if the new frame is a keyframe
// because frame dependencies uses on the frame number diff so frames inside a GOP should have the same offset.
func (f *FrameNumberWrapper) UpdateAndGet(new uint64, updateOffset bool) uint64 {
if !f.inited {
f.last = new
f.inited = true
return new
}
if new <= f.last {
return new + f.offset
}
if updateOffset {
new16 := uint16(new + f.offset)
last16 := uint16(f.last + f.offset)
// if new frame number wraps around and is considered as earlier by client, increase offset to make it later
if diff := new16 - last16; diff > 0x8000 || (diff == 0x8000 && new16 < last16) {
// increase offset by 6000, nearly 10 seconds for 30fps video with 3 spatial layers
prevOffset := f.offset
f.offset += uint64(65535 - diff + 6000)
f.logger.Debugw("wrap around frame number seen, update offset", "new", new, "last", f.last, "offset", f.offset, "prevOffset", prevOffset, "lastWrapFn", last16, "newWrapFn", new16)
}
}
f.last = new
return new + f.offset
}
func (f *FrameNumberWrapper) LastOrigin() uint64 {
return f.last
}