mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-15 21:20:40 +08:00
feat: Prevent concurrent read and write issues when publishers catch up with subscribers after blocking them
desc: 防止订阅者阻塞后,发布者追上订阅者产生并发读写问题
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
@@ -44,14 +45,88 @@ func (r *RTPFrame) Unmarshal(raw []byte) *RTPFrame {
|
||||
return r
|
||||
}
|
||||
|
||||
type IDataFrame[T any] interface {
|
||||
Init() // 初始化
|
||||
Reset() // 重置数据,复用内存
|
||||
Ready() // 标记为可读取
|
||||
ReaderEnter() int32 // 读取者数量+1
|
||||
ReaderLeave() int32 // 读取者数量-1
|
||||
StartWrite() bool // 开始写入
|
||||
SetSequence(uint32) // 设置序号
|
||||
GetSequence() uint32 // 获取序号
|
||||
ReaderCount() int32 // 读取者数量
|
||||
Discard() int32 // 如果写入时还有读取者没有离开则废弃该帧,剥离RingBuffer,防止并发读写
|
||||
IsDiscarded() bool // 是否已废弃
|
||||
IsWriting() bool // 是否正在写入
|
||||
Wait() // 阻塞等待可读取
|
||||
Broadcast() // 广播可读取
|
||||
}
|
||||
|
||||
type DataFrame[T any] struct {
|
||||
DeltaTime uint32 // 相对上一帧时间戳,毫秒
|
||||
WriteTime time.Time // 写入时间,可用于比较两个帧的先后
|
||||
Sequence uint32 // 在一个Track中的序号
|
||||
BytesIn int // 输入字节数用于计算BPS
|
||||
CanRead bool `json:"-" yaml:"-"`
|
||||
Data T `json:"-" yaml:"-"`
|
||||
sync.Cond `json:"-" yaml:"-"`
|
||||
DeltaTime uint32 // 相对上一帧时间戳,毫秒
|
||||
WriteTime time.Time // 写入时间,可用于比较两个帧的先后
|
||||
Sequence uint32 // 在一个Track中的序号
|
||||
BytesIn int // 输入字节数用于计算BPS
|
||||
CanRead bool `json:"-" yaml:"-"` // 是否可读取
|
||||
readerCount atomic.Int32 `json:"-" yaml:"-"` // 读取者数量
|
||||
Data T `json:"-" yaml:"-"`
|
||||
sync.Cond `json:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
func NewDataFrame[T any]() *DataFrame[T] {
|
||||
return &DataFrame[T]{}
|
||||
}
|
||||
func (df *DataFrame[T]) IsWriting() bool {
|
||||
return !df.CanRead
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) IsDiscarded() bool {
|
||||
return df.L == nil
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) Discard() int32 {
|
||||
df.L = nil //标记为废弃
|
||||
return df.readerCount.Load()
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) SetSequence(sequence uint32) {
|
||||
df.Sequence = sequence
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) GetSequence() uint32 {
|
||||
return df.Sequence
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) ReaderEnter() int32 {
|
||||
return df.readerCount.Add(1)
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) ReaderCount() int32 {
|
||||
return df.readerCount.Load()
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) ReaderLeave() int32 {
|
||||
return df.readerCount.Add(-1)
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) StartWrite() bool {
|
||||
if df.readerCount.Load() > 0 {
|
||||
df.Discard() //标记为废弃
|
||||
return false
|
||||
} else {
|
||||
df.CanRead = false //标记为正在写入
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) Ready() {
|
||||
df.WriteTime = time.Now()
|
||||
df.CanRead = true //标记为可读取
|
||||
df.Broadcast()
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) Init() {
|
||||
df.L = EmptyLocker
|
||||
}
|
||||
|
||||
func (df *DataFrame[T]) Reset() {
|
||||
@@ -71,6 +146,10 @@ type AVFrame struct {
|
||||
AUList util.BLLs `json:"-" yaml:"-"` // 裸数据
|
||||
}
|
||||
|
||||
func NewAVFrame() *AVFrame {
|
||||
return &AVFrame{}
|
||||
}
|
||||
|
||||
func (av *AVFrame) WriteAVCC(ts uint32, frame *util.BLL) {
|
||||
if ts == 0 {
|
||||
ts = 1
|
||||
|
Reference in New Issue
Block a user