mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-06-05 11:59:45 +00:00
fix(videochannel): force VP8 keyframes and drop bad frames
This commit is contained in:
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/openlibrecommunity/olcrtc
|
||||
go 1.26.3
|
||||
|
||||
require (
|
||||
codeberg.org/rape4me/kc v0.0.0-20260527043314-71657a097a6f
|
||||
codeberg.org/rape4me/kc v0.0.0-20260527074346-4cb2a45790c2
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
|
||||
github.com/livekit/protocol v1.46.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -7,8 +7,8 @@ buf.build/go/protoyaml v0.7.0/go.mod h1:+a0cavd0uMvirb87xdu2ZMMmjlIQoiH/N2Ich5MG
|
||||
cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs=
|
||||
cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
codeberg.org/rape4me/kc v0.0.0-20260527043314-71657a097a6f h1:amyzfF9+4jCUKJndW336YHbj3FiaWs/qkJqOgUyreCA=
|
||||
codeberg.org/rape4me/kc v0.0.0-20260527043314-71657a097a6f/go.mod h1:ooInikVAZhJE+m+gHIekq52ZFkUPcCZAvY4u/m2M/V0=
|
||||
codeberg.org/rape4me/kc v0.0.0-20260527074346-4cb2a45790c2 h1:u7QorW08YOZGj86cubeGpiwm+d0tMKa0e7syiBkO2eo=
|
||||
codeberg.org/rape4me/kc v0.0.0-20260527074346-4cb2a45790c2/go.mod h1:ooInikVAZhJE+m+gHIekq52ZFkUPcCZAvY4u/m2M/V0=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
|
||||
@@ -20,8 +20,10 @@ type goEncoder struct {
|
||||
}
|
||||
|
||||
func newGoEncoder(width, height, _ int) *goEncoder {
|
||||
enc := vp8.NewEncoder(width, height, 63)
|
||||
enc.SetKeyInterval(1)
|
||||
return &goEncoder{
|
||||
enc: vp8.NewEncoder(width, height, 10),
|
||||
enc: enc,
|
||||
width: width,
|
||||
height: height,
|
||||
frameSize: width * height,
|
||||
@@ -74,12 +76,10 @@ func (d *goDecoder) PushSample(sample []byte) error {
|
||||
}
|
||||
frame, err := d.dec.Decode(sample)
|
||||
if err != nil {
|
||||
// Inter-frame arrived before any keyframe (e.g. SFU started forwarding
|
||||
// mid-GOP). Drop silently; the next keyframe will reset the reference.
|
||||
if errors.Is(err, vp8.ErrNoReference) {
|
||||
return nil
|
||||
return nil // skip inter-frames until keyframe arrives
|
||||
}
|
||||
return fmt.Errorf("vp8 decode: %w", err)
|
||||
return nil // skip undecodable frames (e.g. from other participants)
|
||||
}
|
||||
gray := frame.Grayscale()
|
||||
select {
|
||||
|
||||
@@ -88,9 +88,6 @@ type streamTransport struct {
|
||||
remoteRole byte
|
||||
bindingToken uint32
|
||||
runCtx context.Context //nolint:containedctx,lll // long-lived context drives idle-frame loops bound to this transport's lifetime
|
||||
|
||||
idleFrame []byte
|
||||
idleFrameMu sync.Mutex
|
||||
}
|
||||
|
||||
// New creates a visual videochannel transport backed by a carrier engine.
|
||||
@@ -388,28 +385,18 @@ func (p *streamTransport) Features() transport.Features {
|
||||
}
|
||||
|
||||
func (p *streamTransport) writeIdleFrame(enc *goEncoder, frameDuration time.Duration) {
|
||||
p.idleFrameMu.Lock()
|
||||
cached := p.idleFrame
|
||||
p.idleFrameMu.Unlock()
|
||||
|
||||
if cached == nil {
|
||||
rawFrame, err := p.renderFrame(nil)
|
||||
if err != nil {
|
||||
logger.Debugf("videochannel render idle error: %v", err)
|
||||
return
|
||||
}
|
||||
sample, err := enc.EncodeFrame(rawFrame)
|
||||
if err != nil {
|
||||
logger.Warnf("videochannel encoder idle error: %v", err)
|
||||
return
|
||||
}
|
||||
p.idleFrameMu.Lock()
|
||||
p.idleFrame = sample
|
||||
p.idleFrameMu.Unlock()
|
||||
cached = sample
|
||||
rawFrame, err := p.renderFrame(nil)
|
||||
if err != nil {
|
||||
logger.Debugf("videochannel render idle error: %v", err)
|
||||
return
|
||||
}
|
||||
sample, err := enc.EncodeFrame(rawFrame)
|
||||
if err != nil {
|
||||
logger.Warnf("videochannel encoder idle error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
_ = p.track.WriteSample(media.Sample{Data: cached, Duration: frameDuration})
|
||||
_ = p.track.WriteSample(media.Sample{Data: sample, Duration: frameDuration})
|
||||
}
|
||||
|
||||
func (p *streamTransport) writePayloadFrame(enc *goEncoder, payload []byte, frameDuration time.Duration) {
|
||||
|
||||
Reference in New Issue
Block a user