修复合并写多发重复数据问题

This commit is contained in:
yangjiechina
2024-07-10 23:10:52 +08:00
parent 52832690d1
commit e0dcff6f20
2 changed files with 49 additions and 54 deletions

View File

@@ -29,35 +29,41 @@ type MergeWritingBuffer interface {
ReadSegmentsFromKeyFrameIndex(cb func([]byte)) ReadSegmentsFromKeyFrameIndex(cb func([]byte))
} }
type mwBlock struct {
free bool
keyVideo bool
buffer collections.MemoryPool
}
type mergeWritingBuffer struct { type mergeWritingBuffer struct {
mwBlocks []collections.MemoryPool mwBlocks []mwBlock
//空闲合并写块 //空闲合并写块
freeKeyFrameMWBlocks collections.LinkedList[collections.MemoryPool] keyFrameFreeMWBlocks collections.LinkedList[collections.MemoryPool]
freeNoneKeyFrameMWBlocks collections.LinkedList[collections.MemoryPool] noneKeyFreeFrameMWBlocks collections.LinkedList[collections.MemoryPool]
index int //当前切片位于mwBlocks的索引 index int //当前切片位于mwBlocks的索引
startTS int64 //当前切片的开始时间 startTS int64 //当前切片的开始时间
duration int //当前切片时长 duration int //当前切片时长
lastKeyFrameIndex int //最新关键帧所在切片的索引 lastKeyFrameIndex int //最新关键帧所在切片的索引
keyFrameCount int //关键帧计数
existVideo bool //是否存在视频 existVideo bool //是否存在视频
keyFrameBufferMaxLength int keyFrameBufferMaxLength int
nonKeyFrameBufferMaxLength int nonKeyFrameBufferMaxLength int
keyFrameMap map[int]int
} }
func (m *mergeWritingBuffer) createMWBlock(videoKey bool) collections.MemoryPool { func (m *mergeWritingBuffer) createMWBlock(videoKey bool) mwBlock {
if videoKey { if videoKey {
return collections.NewDirectMemoryPool(m.keyFrameBufferMaxLength) return mwBlock{true, videoKey, collections.NewDirectMemoryPool(m.keyFrameBufferMaxLength)}
} else { } else {
return collections.NewDirectMemoryPool(m.nonKeyFrameBufferMaxLength) return mwBlock{true, false, collections.NewDirectMemoryPool(m.nonKeyFrameBufferMaxLength)}
} }
} }
func (m *mergeWritingBuffer) grow() { func (m *mergeWritingBuffer) grow() {
pools := make([]collections.MemoryPool, cap(m.mwBlocks)*3/2) pools := make([]mwBlock, cap(m.mwBlocks)*3/2)
for i := 0; i < cap(m.mwBlocks); i++ { for i := 0; i < cap(m.mwBlocks); i++ {
pools[i] = m.mwBlocks[i] pools[i] = m.mwBlocks[i]
} }
@@ -67,46 +73,37 @@ func (m *mergeWritingBuffer) grow() {
func (m *mergeWritingBuffer) Allocate(size int, ts int64, videoKey bool) []byte { func (m *mergeWritingBuffer) Allocate(size int, ts int64, videoKey bool) []byte {
if !AppConfig.GOPCache || !m.existVideo { if !AppConfig.GOPCache || !m.existVideo {
return m.mwBlocks[0].Allocate(size) return m.mwBlocks[0].buffer.Allocate(size)
} }
utils.Assert(ts != -1) utils.Assert(ts != -1)
//新的切片 //新的切片
if m.startTS == -1 { if m.startTS == -1 {
if _, ok := m.keyFrameMap[m.index]; ok { m.startTS = ts
delete(m.keyFrameMap, m.index)
}
if m.mwBlocks[m.index] == nil { if m.mwBlocks[m.index].buffer == nil {
//创建内存块 //创建内存块
m.mwBlocks[m.index] = m.createMWBlock(videoKey) m.mwBlocks[m.index] = m.createMWBlock(videoKey)
} else { } else {
//循环使用 //循环使用
if !videoKey { m.mwBlocks[m.index].buffer.Clear()
//I帧间隔长, 不够写一组GOP, 扩容! if m.mwBlocks[m.index].keyVideo {
if len(m.keyFrameMap) < 1 { m.keyFrameCount--
capacity := len(m.mwBlocks)
m.grow()
m.index = capacity
m.mwBlocks[m.index] = m.createMWBlock(videoKey)
}
} }
m.mwBlocks[m.index].Clear()
} }
m.startTS = ts m.mwBlocks[m.index].free = false
m.mwBlocks[m.index].keyVideo = videoKey
} }
if videoKey { if videoKey {
//请务必确保关键帧帧从新的切片开始 //请务必确保关键帧帧从新的切片开始
//外部遇到关键帧请先调用FlushSegment //外部遇到关键帧请先调用FlushSegment
utils.Assert(m.mwBlocks[m.index].IsEmpty()) utils.Assert(m.mwBlocks[m.index].buffer.IsEmpty())
m.lastKeyFrameIndex = m.index m.lastKeyFrameIndex = m.index
m.keyFrameMap[m.index] = m.index m.keyFrameCount++
} }
if ts < m.startTS { if ts < m.startTS {
@@ -114,15 +111,17 @@ func (m *mergeWritingBuffer) Allocate(size int, ts int64, videoKey bool) []byte
} }
m.duration = int(ts - m.startTS) m.duration = int(ts - m.startTS)
return m.mwBlocks[m.index].Allocate(size) return m.mwBlocks[m.index].buffer.Allocate(size)
} }
func (m *mergeWritingBuffer) FlushSegment() []byte { func (m *mergeWritingBuffer) FlushSegment() []byte {
if m.mwBlocks[m.index] == nil { if !AppConfig.GOPCache || !m.existVideo {
return nil
} else if m.mwBlocks[m.index].buffer == nil || m.mwBlocks[m.index].free {
return nil return nil
} }
data, _ := m.mwBlocks[m.index].Data() data, _ := m.mwBlocks[m.index].buffer.Data()
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
@@ -134,16 +133,22 @@ func (m *mergeWritingBuffer) FlushSegment() []byte {
m.nonKeyFrameBufferMaxLength = len(data) * 3 / 2 m.nonKeyFrameBufferMaxLength = len(data) * 3 / 2
} }
m.index = (m.index + 1) % cap(m.mwBlocks) capacity := cap(m.mwBlocks)
if m.index+1 == capacity && m.keyFrameCount == 1 {
m.grow()
}
m.index = (m.index + 1) % capacity
m.startTS = -1 m.startTS = -1
m.duration = 0 m.duration = 0
m.mwBlocks[m.index].free = true
return data return data
} }
func (m *mergeWritingBuffer) PeekCompletedSegment() []byte { func (m *mergeWritingBuffer) PeekCompletedSegment() []byte {
if !AppConfig.GOPCache || !m.existVideo { if !AppConfig.GOPCache || !m.existVideo {
data, _ := m.mwBlocks[0].Data() data, _ := m.mwBlocks[0].buffer.Data()
m.mwBlocks[0].Clear() m.mwBlocks[0].buffer.Clear()
return data return data
} }
@@ -163,38 +168,33 @@ func (m *mergeWritingBuffer) IsFull(ts int64) bool {
} }
func (m *mergeWritingBuffer) IsNewSegment() bool { func (m *mergeWritingBuffer) IsNewSegment() bool {
if m.mwBlocks[m.index] == nil { return m.mwBlocks[m.index].buffer == nil || m.mwBlocks[m.index].free
return true
}
data, _ := m.mwBlocks[m.index].Data()
return len(data) == 0
} }
func (m *mergeWritingBuffer) Reserve(number int) { func (m *mergeWritingBuffer) Reserve(number int) {
utils.Assert(m.mwBlocks[m.index] != nil) utils.Assert(m.mwBlocks[m.index].buffer != nil)
m.mwBlocks[m.index].Reserve(number) m.mwBlocks[m.index].buffer.Reserve(number)
} }
func (m *mergeWritingBuffer) ReadSegmentsFromKeyFrameIndex(cb func([]byte)) { func (m *mergeWritingBuffer) ReadSegmentsFromKeyFrameIndex(cb func([]byte)) {
if m.lastKeyFrameIndex < 0 || m.index == m.lastKeyFrameIndex { if m.keyFrameCount == 0 {
return return
} }
for i := m.lastKeyFrameIndex; i < cap(m.mwBlocks); i++ { for i := m.lastKeyFrameIndex; i < cap(m.mwBlocks); i++ {
if m.mwBlocks[i] == nil { if m.mwBlocks[i].buffer == nil {
continue continue
} }
data, _ := m.mwBlocks[i].Data() data, _ := m.mwBlocks[i].buffer.Data()
cb(data) cb(data)
} }
//回调循环使用的头部数据 //回调循环使用的头部数据
if m.index < m.lastKeyFrameIndex { if m.index < m.lastKeyFrameIndex {
for i := 0; i < m.index; i++ { for i := 0; i < m.index; i++ {
data, _ := m.mwBlocks[i].Data() data, _ := m.mwBlocks[i].buffer.Data()
cb(data) cb(data)
} }
} }
@@ -202,15 +202,15 @@ func (m *mergeWritingBuffer) ReadSegmentsFromKeyFrameIndex(cb func([]byte)) {
func NewMergeWritingBuffer(existVideo bool) MergeWritingBuffer { func NewMergeWritingBuffer(existVideo bool) MergeWritingBuffer {
//开启GOP缓存, 输出流也缓存整个GOP //开启GOP缓存, 输出流也缓存整个GOP
var blocks []collections.MemoryPool var blocks []mwBlock
if existVideo { if existVideo {
blocks = make([]collections.MemoryPool, AppConfig.WriteBufferNumber) blocks = make([]mwBlock, AppConfig.WriteBufferNumber)
} else { } else {
blocks = make([]collections.MemoryPool, 1) blocks = make([]mwBlock, 1)
} }
if !existVideo || !AppConfig.GOPCache { if !existVideo || !AppConfig.GOPCache {
blocks[0] = collections.NewDirectMemoryPool(1024 * 100) blocks[0] = mwBlock{true, false, collections.NewDirectMemoryPool(1024 * 100)}
} }
return &mergeWritingBuffer{ return &mergeWritingBuffer{
@@ -220,6 +220,5 @@ func NewMergeWritingBuffer(existVideo bool) MergeWritingBuffer {
startTS: -1, startTS: -1,
lastKeyFrameIndex: -1, lastKeyFrameIndex: -1,
existVideo: existVideo, existVideo: existVideo,
keyFrameMap: make(map[int]int, 5),
} }
} }

View File

@@ -558,10 +558,6 @@ func (s *PublishSource) OnDeMuxStream(stream utils.AVStream) {
//启动探测超时计时器 //启动探测超时计时器
if len(s.originStreams.All()) == 1 { if len(s.originStreams.All()) == 1 {
if AppConfig.ProbeTimeout == 0 {
AppConfig.ProbeTimeout = 2000
}
s.probeTimer = time.AfterFunc(time.Duration(AppConfig.ProbeTimeout)*time.Millisecond, func() { s.probeTimer = time.AfterFunc(time.Duration(AppConfig.ProbeTimeout)*time.Millisecond, func() {
s.probeTimoutEvent <- true s.probeTimoutEvent <- true
}) })