mirror of
https://github.com/lkmio/lkm.git
synced 2025-10-05 15:16:49 +08:00
117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package stream
|
||
|
||
import (
|
||
"github.com/yangjiechina/avformat/utils"
|
||
)
|
||
|
||
// MemoryPool 从解复用阶段,拼凑成完整的AVPacket开始(写),到GOP缓存结束(释放),整个过程都使用池中内存
|
||
// 类似环形缓冲区, 区别在于,写入的内存块是连续的、整块内存.
|
||
type MemoryPool interface {
|
||
// Mark 标记一块写的内存地址
|
||
//使用流程 Mark->Write/Allocate....->Fetch/Reset
|
||
Mark()
|
||
|
||
Write(data []byte)
|
||
|
||
Allocate(size int) []byte
|
||
|
||
Fetch() []byte
|
||
|
||
// Reset 清空此次Write的标记,本次缓存的数据无效
|
||
Reset()
|
||
|
||
// FreeHead 从头部释放指定大小内存
|
||
FreeHead(size int)
|
||
|
||
// FreeTail 从尾部释放指定大小内存
|
||
FreeTail(size int)
|
||
}
|
||
|
||
func NewMemoryPool(capacity int) MemoryPool {
|
||
pool := &memoryPool{
|
||
data: make([]byte, capacity),
|
||
capacity: capacity,
|
||
}
|
||
|
||
return pool
|
||
}
|
||
|
||
type memoryPool struct {
|
||
data []byte
|
||
ptrStart uintptr
|
||
ptrEnd uintptr
|
||
//剩余的可用内存空间不足以为此次write
|
||
capacity int
|
||
head int
|
||
tail int
|
||
|
||
//保存开始索引
|
||
mark int
|
||
}
|
||
|
||
// 根据head和tail计算出可用的内存地址
|
||
func (m *memoryPool) allocate(size int) []byte {
|
||
if m.capacity-m.tail < size {
|
||
//使用从头释放的内存
|
||
if m.tail-m.mark+size <= m.head {
|
||
copy(m.data, m.data[m.mark:m.tail])
|
||
m.capacity = m.mark
|
||
m.tail = m.tail - m.mark
|
||
m.mark = 0
|
||
} else {
|
||
|
||
//扩容
|
||
capacity := (cap(m.data) + m.tail - m.mark + size) * 3 / 2
|
||
bytes := make([]byte, capacity)
|
||
//不对之前的内存进行复制, 已经被AVPacket引用, 自行GC
|
||
copy(bytes, m.data[m.mark:m.tail])
|
||
m.data = bytes
|
||
m.capacity = capacity
|
||
m.tail = m.tail - m.mark
|
||
m.mark = 0
|
||
m.head = 0
|
||
|
||
}
|
||
}
|
||
|
||
bytes := m.data[m.tail:]
|
||
m.tail += size
|
||
return bytes
|
||
}
|
||
|
||
func (m *memoryPool) Mark() {
|
||
m.mark = m.tail
|
||
}
|
||
|
||
func (m *memoryPool) Write(data []byte) {
|
||
allocate := m.allocate(len(data))
|
||
copy(allocate, data)
|
||
}
|
||
|
||
func (m *memoryPool) Allocate(size int) []byte {
|
||
return m.allocate(size)
|
||
}
|
||
|
||
func (m *memoryPool) Fetch() []byte {
|
||
return m.data[m.mark:m.tail]
|
||
}
|
||
|
||
func (m *memoryPool) Reset() {
|
||
m.tail = m.mark
|
||
}
|
||
|
||
func (m *memoryPool) FreeHead(size int) {
|
||
m.head += size
|
||
if m.head == m.tail {
|
||
m.head = 0
|
||
m.tail = 0
|
||
} else if m.head >= m.capacity {
|
||
m.head = 0
|
||
}
|
||
}
|
||
|
||
func (m *memoryPool) FreeTail(size int) {
|
||
m.tail -= size
|
||
utils.Assert(m.tail >= 0)
|
||
}
|