Files
lkm/stream/stream_buffer.go
2023-11-28 18:47:56 +08:00

130 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package stream
import "github.com/yangjiechina/avformat/utils"
// StreamBuffer GOP缓存
type StreamBuffer interface {
// AddPacket Return bool 缓存帧是否成功, 如果首帧非关键帧, 缓存失败
AddPacket(packet interface{}, key bool, ts int64) bool
// SetDiscardHandler 设置丢弃帧时的回调
SetDiscardHandler(handler func(packet interface{}))
PeekAll(handler func(packet interface{}))
Peek(index int) interface{}
Duration() int64
Size() int
}
type streamBuffer struct {
buffer RingBuffer
duration int64
keyFrameDts int64 //最近一个关键帧的Dts
FarthestKeyFrameDts int64 //最远一个关键帧的Dts
discardHandler func(packet interface{})
}
type element struct {
ts int64
key bool
pkt interface{}
}
func NewStreamBuffer(duration int64) StreamBuffer {
return &streamBuffer{duration: duration, buffer: NewRingBuffer(1000)}
}
func (s *streamBuffer) AddPacket(packet interface{}, key bool, ts int64) bool {
if s.buffer.IsEmpty() {
if !key {
return false
}
s.FarthestKeyFrameDts = ts
}
s.buffer.Push(element{ts, key, packet})
if key {
s.keyFrameDts = ts
}
//丢弃处理
//以最近的关键帧时间戳开始丢弃缓存超过duration长度的帧
//至少需要保障当前GOP完整
//暂时不考虑以下情况:
// 1. 音频收流正常,视频长时间没收流,待视频恢复后。 会造成在此期间,多余的音频帧被丢弃,播放时有画面,没声音.
// 2. 视频反之亦然
if !key {
return true
}
for farthest := s.keyFrameDts - s.duration; s.buffer.Size() > 1 && s.buffer.Head().(element).ts < farthest; {
ele := s.buffer.Pop().(element)
//重新设置最早的关键帧时间戳
if ele.key && ele.ts != s.FarthestKeyFrameDts {
s.FarthestKeyFrameDts = ele.ts
}
if s.discardHandler != nil {
s.discardHandler(ele.pkt)
}
}
return true
}
func (s *streamBuffer) SetDiscardHandler(handler func(packet interface{})) {
s.discardHandler = handler
}
func (s *streamBuffer) Peek(index int) interface{} {
utils.Assert(index < s.buffer.Size())
head, tail := s.buffer.All()
if index < len(head) {
return head[index].(element).pkt
} else {
return tail[index-len(head)].(element).pkt
}
}
func (s *streamBuffer) PeekAll(handler func(packet interface{})) {
head, tail := s.buffer.All()
if head == nil {
return
}
for _, value := range head {
handler(value.(element).pkt)
}
if tail == nil {
return
}
for _, value := range tail {
handler(value.(element).pkt)
}
}
func (s *streamBuffer) Duration() int64 {
head := s.buffer.Head()
tail := s.buffer.Tail()
if head == nil || tail == nil {
return 0
}
return tail.(element).ts - head.(element).ts
}
func (s *streamBuffer) Size() int {
return s.buffer.Size()
}