mirror of
https://github.com/lkmio/lkm.git
synced 2025-09-27 03:26:01 +08:00
130 lines
2.7 KiB
Go
130 lines
2.7 KiB
Go
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()
|
||
}
|