|
|
|
|
// 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]
|
|
|
|
|
}
|