You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/remux/gop_cache_mpegts.go

124 lines
2.9 KiB
Go

// Copyright 2022, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package remux
// TODO(chef) 将gop_cache.go和gop_cache_mpegts.go的待完成项统一记录在这里
// - GopCache 和 GopCacheMpegts 尽量统一
// - 是否有必要单独存储帧也即一个Gop的多个帧是一块内存还是多块内存从性能功能可读考虑
// - GopCache中非gop功能包括meta和header的缓存考虑移动到其他地方
type GopCacheMpegts struct {
uniqueKey string
gopNum int
gopRing []GopMpegts
gopRingFirst int
gopRingLast int
gopSize int
}
func NewGopCacheMpegts(uniqueKey string, gopNum int) *GopCacheMpegts {
return &GopCacheMpegts{
uniqueKey: uniqueKey,
gopNum: gopNum,
gopSize: gopNum + 1,
gopRing: make([]GopMpegts, gopNum+1, gopNum+1),
gopRingFirst: 0,
gopRingLast: 0,
}
}
// Feed
//
// @param b: 内部持有该内存块
//
func (gc *GopCacheMpegts) Feed(b []byte, boundary bool) {
if gc.gopSize > 1 {
if boundary {
gc.feedNewGop(b)
} else {
gc.feedLastGop(b)
}
}
}
// GetGopCount 获取GOP数量注意最后一个可能是不完整的
//
func (gc *GopCacheMpegts) GetGopCount() int {
return (gc.gopRingLast + gc.gopSize - gc.gopRingFirst) % gc.gopSize
}
func (gc *GopCacheMpegts) GetGopDataAt(pos int) [][]byte {
if pos >= gc.GetGopCount() || pos < 0 {
return nil
}
return gc.gopRing[(pos+gc.gopRingFirst)%gc.gopSize].data
}
func (gc *GopCacheMpegts) Clear() {
gc.gopRingLast = 0
gc.gopRingFirst = 0
}
// ---------------------------------------------------------------------------------------------------------------------
// feedLastGop
//
// 往最后一个GOP元素追加一个msg
// 注意如果GopCache为空则不缓存msg
//
func (gc *GopCacheMpegts) feedLastGop(b []byte) {
if !gc.isGopRingEmpty() {
gc.gopRing[(gc.gopRingLast-1+gc.gopSize)%gc.gopSize].Feed(b)
}
}
// feedNewGop
//
// 生成一个最新的GOP元素并往里追加一个msg
//
func (gc *GopCacheMpegts) feedNewGop(b []byte) {
if gc.isGopRingFull() {
gc.gopRingFirst = (gc.gopRingFirst + 1) % gc.gopSize
}
gc.gopRing[gc.gopRingLast].Clear()
gc.gopRing[gc.gopRingLast].Feed(b)
gc.gopRingLast = (gc.gopRingLast + 1) % gc.gopSize
}
func (gc *GopCacheMpegts) isGopRingFull() bool {
return (gc.gopRingLast+1)%gc.gopSize == gc.gopRingFirst
}
func (gc *GopCacheMpegts) isGopRingEmpty() bool {
return gc.gopRingFirst == gc.gopRingLast
}
// ---------------------------------------------------------------------------------------------------------------------
// GopMpegts
//
// 单个Gop包含多帧数据
//
type GopMpegts struct {
data [][]byte
}
// Feed
//
// @param b: 内部持有`b`内存块
//
func (g *GopMpegts) Feed(b []byte) {
g.data = append(g.data, b)
}
func (g *GopMpegts) Clear() {
g.data = g.data[:0]
}