package flexfec
import (
"errors"
"sync"
"github.com/pion/interceptor"
"github.com/pion/rtp"
)
type streamState struct {
mu sync .Mutex
flexFecEncoder FlexEncoder
packetBuffer []rtp .Packet
}
type FecInterceptor struct {
interceptor .NoOp
mu sync .Mutex
streams map [uint32 ]*streamState
numMediaPackets uint32
numFecPackets uint32
encoderFactory EncoderFactory
}
type FecInterceptorFactory struct {
opts []FecOption
}
func NewFecInterceptor (opts ...FecOption ) (*FecInterceptorFactory , error ) {
return &FecInterceptorFactory {opts : opts }, nil
}
func (r *FecInterceptorFactory ) NewInterceptor (_ string ) (interceptor .Interceptor , error ) {
interceptor := &FecInterceptor {
streams : make (map [uint32 ]*streamState ),
numMediaPackets : 5 ,
numFecPackets : 2 ,
encoderFactory : FlexEncoder03Factory {},
}
for _ , opt := range r .opts {
if err := opt (interceptor ); err != nil {
return nil , err
}
}
return interceptor , nil
}
func (r *FecInterceptor ) UnbindLocalStream (info *interceptor .StreamInfo ) {
r .mu .Lock ()
defer r .mu .Unlock ()
delete (r .streams , info .SSRC )
}
func (r *FecInterceptor ) BindLocalStream (
info *interceptor .StreamInfo , writer interceptor .RTPWriter ,
) interceptor .RTPWriter {
if info .PayloadTypeForwardErrorCorrection == 0 || info .SSRCForwardErrorCorrection == 0 {
return writer
}
mediaSSRC := info .SSRC
r .mu .Lock ()
stream := &streamState {
flexFecEncoder : r .encoderFactory .NewEncoder (info .PayloadTypeForwardErrorCorrection , info .SSRCForwardErrorCorrection ),
packetBuffer : make ([]rtp .Packet , 0 ),
}
r .streams [mediaSSRC ] = stream
r .mu .Unlock ()
return interceptor .RTPWriterFunc (
func (header *rtp .Header , payload []byte , attributes interceptor .Attributes ) (int , error ) {
if header .SSRC != mediaSSRC {
return writer .Write (header , payload , attributes )
}
var fecPackets []rtp .Packet
stream .mu .Lock ()
stream .packetBuffer = append (stream .packetBuffer , rtp .Packet {
Header : *header ,
Payload : payload ,
})
if len (stream .packetBuffer ) == int (r .numMediaPackets ) {
fecPackets = stream .flexFecEncoder .EncodeFec (stream .packetBuffer , r .numFecPackets )
stream .packetBuffer = nil
}
stream .mu .Unlock ()
var errs []error
result , err := writer .Write (header , payload , attributes )
if err != nil {
errs = append (errs , err )
}
for _ , packet := range fecPackets {
header := packet .Header
_, err = writer .Write (&header , packet .Payload , attributes )
if err != nil {
errs = append (errs , err )
}
}
return result , errors .Join (errs ...)
},
)
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .