mirror of
https://github.com/lkmio/lkm.git
synced 2025-09-27 03:26:01 +08:00
92 lines
2.3 KiB
Go
92 lines
2.3 KiB
Go
package stream
|
|
|
|
import (
|
|
"github.com/lkmio/avformat"
|
|
"github.com/lkmio/avformat/collections"
|
|
"github.com/lkmio/avformat/utils"
|
|
)
|
|
|
|
// GOPBuffer GOP缓存
|
|
type GOPBuffer interface {
|
|
|
|
// AddPacket Return bool 缓存帧是否成功, 如果首帧非关键帧, 缓存失败
|
|
AddPacket(packet *collections.ReferenceCounter[*avformat.AVPacket]) bool
|
|
|
|
PeekAll(handler func(*collections.ReferenceCounter[*avformat.AVPacket]))
|
|
|
|
Peek(index int) *collections.ReferenceCounter[*avformat.AVPacket]
|
|
|
|
PopAll(handler func(*collections.ReferenceCounter[*avformat.AVPacket]))
|
|
|
|
RequiresClear(nextPacket *collections.ReferenceCounter[*avformat.AVPacket]) bool
|
|
|
|
Size() int
|
|
}
|
|
|
|
type streamBuffer struct {
|
|
buffer collections.RingBuffer[*collections.ReferenceCounter[*avformat.AVPacket]]
|
|
hasVideoKeyFrame bool
|
|
}
|
|
|
|
func (s *streamBuffer) AddPacket(packet *collections.ReferenceCounter[*avformat.AVPacket]) bool {
|
|
if utils.AVMediaTypeVideo == packet.Get().MediaType {
|
|
if packet.Get().Key {
|
|
s.hasVideoKeyFrame = true
|
|
} else if !s.hasVideoKeyFrame {
|
|
// 丢弃首帧非关键视频帧
|
|
return false
|
|
}
|
|
}
|
|
|
|
s.buffer.Push(packet)
|
|
return true
|
|
}
|
|
|
|
func (s *streamBuffer) Peek(index int) *collections.ReferenceCounter[*avformat.AVPacket] {
|
|
utils.Assert(index < s.buffer.Size())
|
|
head, tail := s.buffer.Data()
|
|
|
|
if index < len(head) {
|
|
return head[index]
|
|
} else {
|
|
return tail[index-len(head)]
|
|
}
|
|
}
|
|
|
|
func (s *streamBuffer) PeekAll(handler func(packet *collections.ReferenceCounter[*avformat.AVPacket])) {
|
|
head, tail := s.buffer.Data()
|
|
|
|
if head != nil {
|
|
for _, value := range head {
|
|
handler(value)
|
|
}
|
|
}
|
|
|
|
if tail != nil {
|
|
for _, value := range tail {
|
|
handler(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *streamBuffer) Size() int {
|
|
return s.buffer.Size()
|
|
}
|
|
|
|
func (s *streamBuffer) PopAll(handler func(packet *collections.ReferenceCounter[*avformat.AVPacket])) {
|
|
for s.buffer.Size() > 0 {
|
|
pkt := s.buffer.Pop()
|
|
handler(pkt)
|
|
}
|
|
|
|
s.hasVideoKeyFrame = false
|
|
}
|
|
|
|
func (s *streamBuffer) RequiresClear(nextPacket *collections.ReferenceCounter[*avformat.AVPacket]) bool {
|
|
return s.Size()+1 == s.buffer.Capacity() || (s.hasVideoKeyFrame && utils.AVMediaTypeVideo == nextPacket.Get().MediaType && nextPacket.Get().Key)
|
|
}
|
|
|
|
func NewStreamBuffer() GOPBuffer {
|
|
return &streamBuffer{buffer: collections.NewRingBuffer[*collections.ReferenceCounter[*avformat.AVPacket]](1000), hasVideoKeyFrame: false}
|
|
}
|